diff options
Diffstat (limited to 'Zend')
537 files changed, 11740 insertions, 14829 deletions
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index d6919ae1e1..fc4634580e 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -148,8 +148,6 @@ _LT_AC_TRY_DLOPEN_SELF([ dnl Checks for library functions. AC_CHECK_FUNCS(getpid kill finite sigsetjmp) -AC_CHECK_DECLS([isfinite, isnan, isinf], [], [], [[#include <math.h>]]) - ZEND_CHECK_FLOAT_PRECISION dnl Test whether double cast to long preserves least significant bits. @@ -157,6 +155,7 @@ AC_MSG_CHECKING(whether double cast to long preserves least significant bits) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include <limits.h> +#include <stdlib.h> int main() { @@ -191,11 +190,11 @@ dnl LIBZEND_OTHER_CHECKS dnl AC_DEFUN([LIBZEND_OTHER_CHECKS],[ -AC_ARG_ENABLE([maintainer-zts], - [AS_HELP_STRING([--enable-maintainer-zts], - [Enable thread safety - for code maintainers only!!])], - [ZEND_MAINTAINER_ZTS=$enableval], - [ZEND_MAINTAINER_ZTS=no]) +AC_ARG_ENABLE([zts], + [AS_HELP_STRING([--enable-zts], + [Enable thread safety])], + [ZEND_ZTS=$enableval], + [ZEND_ZTS=no]) AC_ARG_ENABLE([inline-optimization], [AS_HELP_STRING([--disable-inline-optimization], @@ -204,7 +203,7 @@ AC_ARG_ENABLE([inline-optimization], [ZEND_INLINE_OPTIMIZATION=yes]) AC_MSG_CHECKING(whether to enable thread-safety) -AC_MSG_RESULT($ZEND_MAINTAINER_ZTS) +AC_MSG_RESULT($ZEND_ZTS) AC_MSG_CHECKING(whether to enable inline optimization for GCC) AC_MSG_RESULT($ZEND_INLINE_OPTIMIZATION) @@ -225,7 +224,7 @@ fi test -n "$GCC" && CFLAGS="$CFLAGS -Wall -Wno-strict-aliasing" test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS" -if test "$ZEND_MAINTAINER_ZTS" = "yes"; then +if test "$ZEND_ZTS" = "yes"; then AC_DEFINE(ZTS,1,[ ]) CFLAGS="$CFLAGS -DZTS" fi @@ -256,6 +255,7 @@ AC_MSG_CHECKING(for MM alignment and log values) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include <stdio.h> +#include <stdlib.h> typedef union _mm_align_test { void *ptr; @@ -385,135 +385,6 @@ else fi AC_MSG_RESULT($ZEND_GCC_GLOBAL_REGS) -dnl Check if atof() accepts NAN. -AC_CACHE_CHECK(whether atof() accepts NAN, ac_cv_atof_accept_nan,[ -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <math.h> -#include <stdlib.h> - -#ifdef HAVE_ISNAN -#define zend_isnan(a) isnan(a) -#elif defined(HAVE_FPCLASS) -#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN)) -#else -#define zend_isnan(a) 0 -#endif - -int main(int argc, char** argv) -{ - return zend_isnan(atof("NAN")) ? 0 : 1; -} -]])],[ - ac_cv_atof_accept_nan=yes -],[ - ac_cv_atof_accept_nan=no -],[ - ac_cv_atof_accept_nan=no -])]) -if test "$ac_cv_atof_accept_nan" = "yes"; then - AC_DEFINE([HAVE_ATOF_ACCEPTS_NAN], 1, [whether atof() accepts NAN]) -fi - -dnl Check if atof() accepts INF. -AC_CACHE_CHECK(whether atof() accepts INF, ac_cv_atof_accept_inf,[ -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <math.h> -#include <stdlib.h> - -#ifdef HAVE_ISINF -#define zend_isinf(a) isinf(a) -#elif defined(INFINITY) -/* Might not work, but is required by ISO C99 */ -#define zend_isinf(a) (((a)==INFINITY)?1:0) -#elif defined(HAVE_FPCLASS) -#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF)) -#else -#define zend_isinf(a) 0 -#endif - -int main(int argc, char** argv) -{ - return zend_isinf(atof("INF")) && zend_isinf(atof("-INF")) ? 0 : 1; -} -]])],[ - ac_cv_atof_accept_inf=yes -],[ - ac_cv_atof_accept_inf=no -],[ - ac_cv_atof_accept_inf=no -])]) -if test "$ac_cv_atof_accept_inf" = "yes"; then - AC_DEFINE([HAVE_ATOF_ACCEPTS_INF], 1, [whether atof() accepts INF]) -fi - -dnl Check if HUGE_VAL == INF. -AC_CACHE_CHECK(whether HUGE_VAL == INF, ac_cv_huge_val_inf,[ -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <math.h> -#include <stdlib.h> - -#ifdef HAVE_ISINF -#define zend_isinf(a) isinf(a) -#elif defined(INFINITY) -/* Might not work, but is required by ISO C99 */ -#define zend_isinf(a) (((a)==INFINITY)?1:0) -#elif defined(HAVE_FPCLASS) -#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF)) -#else -#define zend_isinf(a) 0 -#endif - -int main(int argc, char** argv) -{ - return zend_isinf(HUGE_VAL) ? 0 : 1; -} -]])],[ - ac_cv_huge_val_inf=yes -],[ - ac_cv_huge_val_inf=no -],[ - ac_cv_huge_val_inf=yes -])]) -dnl This is the most probable fallback so we assume yes in case of cross compile. -if test "$ac_cv_huge_val_inf" = "yes"; then - AC_DEFINE([HAVE_HUGE_VAL_INF], 1, [whether HUGE_VAL == INF]) -fi - -dnl Check if HUGE_VAL + -HUGEVAL == NAN. -AC_CACHE_CHECK(whether HUGE_VAL + -HUGEVAL == NAN, ac_cv_huge_val_nan,[ -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <math.h> -#include <stdlib.h> - -#ifdef HAVE_ISNAN -#define zend_isnan(a) isnan(a) -#elif defined(HAVE_FPCLASS) -#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN)) -#else -#define zend_isnan(a) 0 -#endif - -int main(int argc, char** argv) -{ -#if defined(__sparc__) && !(__GNUC__ >= 3) - /* prevent bug #27830 */ - return 1; -#else - return zend_isnan(HUGE_VAL + -HUGE_VAL) ? 0 : 1; -#endif -} -]])],[ - ac_cv_huge_val_nan=yes -],[ - ac_cv_huge_val_nan=no -],[ - ac_cv_huge_val_nan=yes -])]) -dnl This is the most probable fallback so we assume yes in case of cross compile. -if test "$ac_cv_huge_val_nan" = "yes"; then - AC_DEFINE([HAVE_HUGE_VAL_NAN], 1, [whether HUGE_VAL + -HUGEVAL == NAN]) -fi - dnl Check whether __cpuid_count is available. AC_CACHE_CHECK(whether __cpuid_count is available, ac_cv_cpuid_count_available, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ diff --git a/Zend/tests/004.phpt b/Zend/tests/004.phpt index 179684d076..2f733f1bd8 100644 --- a/Zend/tests/004.phpt +++ b/Zend/tests/004.phpt @@ -3,7 +3,6 @@ strncmp() tests --FILE-- <?php -var_dump(strncmp("", "")); var_dump(strncmp("", "", 100)); var_dump(strncmp("aef", "dfsgbdf", -1)); var_dump(strncmp("fghjkl", "qwer", 0)); @@ -13,8 +12,6 @@ var_dump(strncmp("qwerty", "qwerty123", 7)); echo "Done\n"; ?> --EXPECTF-- -Warning: strncmp() expects exactly 3 parameters, 2 given in %s on line %d -NULL int(0) Warning: Length must be greater than or equal to 0 in %s on line %d diff --git a/Zend/tests/005.phpt b/Zend/tests/005.phpt index 6ad1b0f63d..f4abfb6c51 100644 --- a/Zend/tests/005.phpt +++ b/Zend/tests/005.phpt @@ -3,7 +3,6 @@ strcasecmp() tests --FILE-- <?php -var_dump(strcasecmp("")); var_dump(strcasecmp("", "")); var_dump(strcasecmp("aef", "dfsgbdf")); var_dump(strcasecmp("qwe", "qwer")); @@ -15,8 +14,6 @@ var_dump(strcasecmp("01", "01")); echo "Done\n"; ?> --EXPECTF-- -Warning: strcasecmp() expects exactly 2 parameters, 1 given in %s on line %d -NULL int(0) int(-3) int(-1) diff --git a/Zend/tests/006.phpt b/Zend/tests/006.phpt index 64c74ff134..12907fd36e 100644 --- a/Zend/tests/006.phpt +++ b/Zend/tests/006.phpt @@ -3,7 +3,6 @@ strncasecmp() tests --FILE-- <?php -var_dump(strncasecmp("")); var_dump(strncasecmp("", "", -1)); var_dump(strncasecmp("aef", "dfsgbdf", 0)); var_dump(strncasecmp("aef", "dfsgbdf", 10)); @@ -16,9 +15,6 @@ var_dump(strncasecmp("01", "01", 1000)); echo "Done\n"; ?> --EXPECTF-- -Warning: strncasecmp() expects exactly 3 parameters, 1 given in %s on line %d -NULL - Warning: Length must be greater than or equal to 0 in %s on line %d bool(false) int(0) diff --git a/Zend/tests/007.phpt b/Zend/tests/007.phpt deleted file mode 100644 index 6120181269..0000000000 --- a/Zend/tests/007.phpt +++ /dev/null @@ -1,65 +0,0 @@ ---TEST-- -each() tests ---FILE-- -<?php - -var_dump(each()); -$var = 1; -var_dump(each($var)); -$var = "string"; -var_dump(each($var)); -$var = array(1,2,3); -var_dump(each($var)); -$var = array("a"=>1,"b"=>2,"c"=>3); -var_dump(each($var)); - -$a = array(1); -$a [] =&$a[0]; - -var_dump(each($a)); - - -echo "Done\n"; -?> ---EXPECTF-- -Warning: each() expects exactly 1 parameter, 0 given in %s on line %d -NULL - -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d - -Warning: Variable passed to each() is not an array or object in %s on line %d -NULL - -Warning: Variable passed to each() is not an array or object in %s on line %d -NULL -array(4) { - [1]=> - int(1) - ["value"]=> - int(1) - [0]=> - int(0) - ["key"]=> - int(0) -} -array(4) { - [1]=> - int(1) - ["value"]=> - int(1) - [0]=> - string(1) "a" - ["key"]=> - string(1) "a" -} -array(4) { - [1]=> - int(1) - ["value"]=> - int(1) - [0]=> - int(0) - ["key"]=> - int(0) -} -Done diff --git a/Zend/tests/008.phpt b/Zend/tests/008.phpt index 0766c3e1a4..6f885c0dc5 100644 --- a/Zend/tests/008.phpt +++ b/Zend/tests/008.phpt @@ -3,12 +3,13 @@ define() tests --FILE-- <?php -var_dump(define()); -var_dump(define("TRUE")); -var_dump(define("TRUE", 1)); -var_dump(define("TRUE", 1, array(1))); +try { + var_dump(define(array(1,2,3,4,5), 1)); +} catch (TypeError $e) { + echo "TypeError: ", $e->getMessage(), "\n"; +} -var_dump(define(array(1,2,3,4,5), 1)); +var_dump(define("TRUE", 1)); var_dump(define(" ", 1)); var_dump(define("[[[", 2)); var_dump(define("test const", 3)); @@ -24,18 +25,10 @@ var_dump(constant("test const")); echo "Done\n"; ?> --EXPECTF-- -Warning: define() expects at least 2 parameters, 0 given in %s on line %d -NULL - -Warning: define() expects at least 2 parameters, 1 given in %s on line %d -NULL -bool(true) - -Warning: define() expects parameter 3 to be bool, array given in %s on line %d -NULL +TypeError: define() expects parameter 1 to be string, array given -Warning: define() expects parameter 1 to be string, array given in %s on line %d -NULL +Notice: Constant TRUE already defined in %s on line %d +bool(false) bool(true) bool(true) bool(true) diff --git a/Zend/tests/009.phpt b/Zend/tests/009.phpt index 82cfabee49..15449df3d1 100644 --- a/Zend/tests/009.phpt +++ b/Zend/tests/009.phpt @@ -9,16 +9,17 @@ class foo { } function testNull () { - var_dump(get_class(null)); + try { + var_dump(get_class(null)); + } catch (TypeError $e) { + echo $e->getMessage(), "\n"; + } } } class foo2 extends foo { } -foo::bar(); -foo2::bar(); - $f1 = new foo; $f2 = new foo2; @@ -26,7 +27,11 @@ $f1->bar(); $f2->bar(); var_dump(get_class()); -var_dump(get_class("qwerty")); +try { + var_dump(get_class("qwerty")); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} var_dump(get_class($f1)); var_dump(get_class($f2)); @@ -36,22 +41,13 @@ $f1->testNull(); echo "Done\n"; ?> --EXPECTF-- -Deprecated: Non-static method foo::bar() should not be called statically in %s on line %d -string(3) "foo" - -Deprecated: Non-static method foo::bar() should not be called statically in %s on line %d -string(3) "foo" string(3) "foo" string(3) "foo" Warning: get_class() called without object from outside a class in %s on line %d bool(false) - -Warning: get_class() expects parameter 1 to be object, string given in %s on line %d -bool(false) +get_class() expects parameter 1 to be object, string given string(3) "foo" string(4) "foo2" - -Warning: get_class() expects parameter 1 to be object, null given in %s on line %d -bool(false) +get_class() expects parameter 1 to be object, null given Done diff --git a/Zend/tests/011.phpt b/Zend/tests/011.phpt index 7bcab0798f..d36ae80ae8 100644 --- a/Zend/tests/011.phpt +++ b/Zend/tests/011.phpt @@ -23,8 +23,6 @@ class bar extends foo { } } -var_dump(property_exists()); -var_dump(property_exists("")); var_dump(property_exists("foo","pp1")); var_dump(property_exists("foo","pp2")); var_dump(property_exists("foo","pp3")); @@ -53,11 +51,6 @@ $bar->test(); echo "Done\n"; ?> --EXPECTF-- -Warning: property_exists() expects exactly 2 parameters, 0 given in %s on line %d -NULL - -Warning: property_exists() expects exactly 2 parameters, 1 given in %s on line %d -NULL bool(true) bool(true) bool(true) diff --git a/Zend/tests/012.phpt b/Zend/tests/012.phpt index 40f68e9794..c238229066 100644 --- a/Zend/tests/012.phpt +++ b/Zend/tests/012.phpt @@ -6,10 +6,8 @@ class_exists() tests class foo { } -var_dump(class_exists()); var_dump(class_exists("qwerty")); var_dump(class_exists("")); -var_dump(class_exists(array())); var_dump(class_exists("test", false)); var_dump(class_exists("foo", false)); var_dump(class_exists("foo")); @@ -18,14 +16,9 @@ var_dump(class_exists("stdClass")); echo "Done\n"; ?> ---EXPECTF-- -Warning: class_exists() expects at least 1 parameter, 0 given in %s on line %d -NULL +--EXPECT-- bool(false) bool(false) - -Warning: class_exists() expects parameter 1 to be string, array given in %s on line %d -NULL bool(false) bool(true) bool(true) diff --git a/Zend/tests/013.phpt b/Zend/tests/013.phpt index aec10e53f1..fd8320b536 100644 --- a/Zend/tests/013.phpt +++ b/Zend/tests/013.phpt @@ -6,10 +6,8 @@ interface_exists() tests interface foo { } -var_dump(interface_exists()); var_dump(interface_exists("qwerty")); var_dump(interface_exists("")); -var_dump(interface_exists(array())); var_dump(interface_exists("test", false)); var_dump(interface_exists("foo", false)); var_dump(interface_exists("foo")); @@ -18,14 +16,9 @@ var_dump(interface_exists("stdClass")); echo "Done\n"; ?> ---EXPECTF-- -Warning: interface_exists() expects at least 1 parameter, 0 given in %s on line %d -NULL +--EXPECT-- bool(false) bool(false) - -Warning: interface_exists() expects parameter 1 to be string, array given in %s on line %d -NULL bool(false) bool(true) bool(true) diff --git a/Zend/tests/014.phpt b/Zend/tests/014.phpt index a2c5335923..c02fee9385 100644 --- a/Zend/tests/014.phpt +++ b/Zend/tests/014.phpt @@ -8,13 +8,9 @@ var_dump(get_included_files()); include(__DIR__."/014.inc"); var_dump(get_included_files()); -var_dump(get_included_files(1,1)); - include_once(__DIR__."/014.inc"); var_dump(get_included_files()); -var_dump(get_included_files(1)); - include(__DIR__."/014.inc"); var_dump(get_included_files()); @@ -31,18 +27,12 @@ array(2) { [1]=> string(%d) "%s" } - -Warning: get_included_files() expects exactly 0 parameters, 2 given in %s on line %d -NULL array(2) { [0]=> string(%d) "%s" [1]=> string(%d) "%s" } - -Warning: get_included_files() expects exactly 0 parameters, 1 given in %s on line %d -NULL array(2) { [0]=> string(%d) "%s" diff --git a/Zend/tests/015.phpt b/Zend/tests/015.phpt index ccf5e4ddb0..deea89d14d 100644 --- a/Zend/tests/015.phpt +++ b/Zend/tests/015.phpt @@ -3,9 +3,7 @@ trigger_error() tests --FILE-- <?php -var_dump(trigger_error()); var_dump(trigger_error("error")); -var_dump(trigger_error(array())); var_dump(trigger_error("error", -1)); var_dump(trigger_error("error", 0)); var_dump(trigger_error("error", E_USER_WARNING)); @@ -14,15 +12,9 @@ var_dump(trigger_error("error", E_USER_DEPRECATED)); echo "Done\n"; ?> --EXPECTF-- -Warning: trigger_error() expects at least 1 parameter, 0 given in %s on line %d -NULL - Notice: error in %s on line %d bool(true) -Warning: trigger_error() expects parameter 1 to be string, array given in %s on line %d -NULL - Warning: Invalid error type specified in %s on line %d bool(false) diff --git a/Zend/tests/017.phpt b/Zend/tests/017.phpt index ed1b2a38a5..619365cbce 100644 --- a/Zend/tests/017.phpt +++ b/Zend/tests/017.phpt @@ -3,8 +3,6 @@ builtin functions tests --FILE-- <?php -var_dump(get_resource_type()); -var_dump(get_resource_type("")); $fp = fopen(__FILE__, "r"); var_dump(get_resource_type($fp)); fclose($fp); @@ -14,11 +12,9 @@ var_dump(gettype(get_loaded_extensions())); var_dump(count(get_loaded_extensions())); var_dump(gettype(get_loaded_extensions(true))); var_dump(count(get_loaded_extensions(true))); -var_dump(get_loaded_extensions(true, true)); define("USER_CONSTANT", "test"); -var_dump(get_defined_constants(true, true)); var_dump(gettype(get_defined_constants(true))); var_dump(gettype(get_defined_constants())); var_dump(count(get_defined_constants())); @@ -29,11 +25,9 @@ function test () { var_dump(gettype(get_defined_functions())); var_dump(count(get_defined_functions())); -var_dump(get_declared_interfaces(true)); var_dump(gettype(get_declared_interfaces())); var_dump(count(get_declared_interfaces())); -var_dump(get_extension_funcs()); var_dump(get_extension_funcs(true)); var_dump(gettype(get_extension_funcs("standard"))); var_dump(count(get_extension_funcs("standard"))); @@ -44,36 +38,19 @@ var_dump(count(get_extension_funcs("zend"))); echo "Done\n"; ?> --EXPECTF-- -Warning: get_resource_type() expects exactly 1 parameter, 0 given in %s on line %d -NULL - -Warning: get_resource_type() expects parameter 1 to be resource, string given in %s on line %d -NULL string(6) "stream" string(7) "Unknown" string(5) "array" int(%d) string(5) "array" int(%d) - -Warning: get_loaded_extensions() expects at most 1 parameter, 2 given in %s on line %d -NULL - -Warning: get_defined_constants() expects at most 1 parameter, 2 given in %s on line %d -NULL string(5) "array" string(5) "array" int(%d) string(5) "array" int(%d) - -Warning: get_declared_interfaces() expects exactly 0 parameters, 1 given in %s on line %d -NULL string(5) "array" int(%d) - -Warning: get_extension_funcs() expects exactly 1 parameter, 0 given in %s on line %d -NULL bool(false) string(5) "array" int(%d) diff --git a/Zend/tests/018.phpt b/Zend/tests/018.phpt index 5ced729fce..97e53b1050 100644 --- a/Zend/tests/018.phpt +++ b/Zend/tests/018.phpt @@ -3,12 +3,8 @@ constant() tests --FILE-- <?php -var_dump(constant()); -var_dump(constant("", "")); var_dump(constant("")); -var_dump(constant(array())); - define("TEST_CONST", 1); var_dump(constant("TEST_CONST")); @@ -18,17 +14,8 @@ var_dump(constant("TEST_CONST2")); echo "Done\n"; ?> --EXPECTF-- -Warning: constant() expects exactly 1 parameter, 0 given in %s on line %d -NULL - -Warning: constant() expects exactly 1 parameter, 2 given in %s on line %d -NULL - Warning: constant(): Couldn't find constant in %s on line %d NULL - -Warning: constant() expects parameter 1 to be string, array given in %s on line %d -NULL int(1) string(4) "test" Done diff --git a/Zend/tests/019.phpt b/Zend/tests/019.phpt index cde590734f..4ea10e9721 100644 --- a/Zend/tests/019.phpt +++ b/Zend/tests/019.phpt @@ -360,7 +360,6 @@ var_dump($global_var); //Note: No error conditions relating to passing arguments can be tested // because these are not functions but statements, it will result in syntax error. ?> -===DONE=== --EXPECTF-- *** Testing unset(), empty() & isset() with scalar variables *** -- Iteration 1 -- @@ -368,7 +367,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -380,7 +379,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -392,7 +391,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -404,7 +403,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -416,7 +415,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -428,7 +427,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -440,7 +439,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -452,7 +451,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -464,7 +463,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -476,7 +475,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -488,7 +487,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -500,7 +499,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -512,7 +511,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -524,7 +523,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -536,7 +535,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -548,7 +547,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -560,7 +559,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -572,7 +571,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -584,7 +583,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -596,7 +595,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -608,7 +607,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -620,7 +619,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -632,7 +631,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -644,7 +643,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -656,7 +655,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -668,7 +667,7 @@ bool(true) bool(true) bool(false) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -680,7 +679,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: scalar_var in %s on line %d +Warning: Undefined variable: scalar_var in %s on line %d NULL bool(false) bool(false) @@ -697,7 +696,7 @@ bool(true) bool(true) bool(true) -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -713,18 +712,18 @@ bool(true) array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -740,18 +739,18 @@ bool(true) array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -767,18 +766,18 @@ bool(true) array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -794,18 +793,18 @@ bool(true) array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -827,13 +826,13 @@ array(3) { int(4) } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(3) { [1]=> @@ -851,13 +850,13 @@ array(2) { int(4) } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(2) { [2]=> @@ -871,13 +870,13 @@ array(1) { int(4) } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(1) { [3]=> @@ -887,18 +886,18 @@ array(1) { array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -918,13 +917,13 @@ array(2) { float(5.6) } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(2) { [1]=> @@ -938,13 +937,13 @@ array(1) { float(5.6) } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(1) { [2]=> @@ -954,18 +953,18 @@ array(1) { array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -983,13 +982,13 @@ array(1) { string(3) "two" } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(1) { [2]=> @@ -999,18 +998,18 @@ array(1) { array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -1028,13 +1027,13 @@ array(1) { string(2) "30" } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(1) { ["Age"]=> @@ -1044,18 +1043,18 @@ array(1) { array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -1079,13 +1078,13 @@ array(4) { string(0) "" } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(4) { [1]=> @@ -1107,13 +1106,13 @@ array(3) { string(0) "" } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(3) { ["One"]=> @@ -1131,13 +1130,13 @@ array(2) { string(0) "" } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(2) { [2]=> @@ -1151,13 +1150,13 @@ array(1) { string(0) "" } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(1) { [""]=> @@ -1167,18 +1166,18 @@ array(1) { array(0) { } -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(false) -Notice: Undefined variable: key_val in %s on line %d +Warning: Undefined variable: key_val in %s on line %d bool(true) array(0) { } -Notice: Undefined variable: array_var in %s on line %d +Warning: Undefined variable: array_var in %s on line %d NULL bool(false) bool(false) @@ -1196,7 +1195,7 @@ bool(true) bool(false) bool(false) -Notice: Undefined variable: resource in %s on line %d +Warning: Undefined variable: resource in %s on line %d NULL -- Iteration 2 -- resource(%d) of type (stream) @@ -1209,10 +1208,10 @@ bool(true) bool(false) bool(false) -Notice: Undefined variable: resource in %s on line %d +Warning: Undefined variable: resource in %s on line %d NULL -Notice: Undefined variable: resources in %s on line %d +Warning: Undefined variable: resources in %s on line %d NULL bool(false) bool(true) @@ -1229,16 +1228,16 @@ object(Point)#%d (3) { bool(true) bool(false) -Notice: Undefined variable: lable in %s on line %d +Warning: Undefined variable: lable in %s on line %d bool(false) -Notice: Undefined variable: lable in %s on line %d +Warning: Undefined variable: lable in %s on line %d bool(true) -Notice: Undefined variable: lable in %s on line %d +Warning: Undefined variable: lable in %s on line %d bool(false) -Notice: Undefined variable: lable in %s on line %d +Warning: Undefined variable: lable in %s on line %d bool(true) object(Point)#%d (3) { ["x"]=> @@ -1263,7 +1262,7 @@ bool(false) bool(false) bool(true) -Notice: Undefined variable: point1 in %s on line %d +Warning: Undefined variable: point1 in %s on line %d NULL bool(false) bool(true) @@ -1293,7 +1292,7 @@ value of static_var before unset: 1 bool(true) bool(false) -Notice: Undefined variable: static_var in %s on line %d +Warning: Undefined variable: static_var in %s on line %d value of static_var after unset: bool(false) bool(true) @@ -1302,7 +1301,7 @@ value of static_var before unset: 2 bool(true) bool(false) -Notice: Undefined variable: static_var in %s on line %d +Warning: Undefined variable: static_var in %s on line %d value of static_var after unset: bool(false) bool(true) @@ -1311,7 +1310,7 @@ value of static_var before unset: 3 bool(true) bool(false) -Notice: Undefined variable: static_var in %s on line %d +Warning: Undefined variable: static_var in %s on line %d value of static_var after unset: bool(false) bool(true) @@ -1330,4 +1329,3 @@ bool(false) bool(false) bool(true) int(10) -===DONE=== diff --git a/Zend/tests/020.phpt b/Zend/tests/020.phpt index 1e2bcff387..efc221cb4f 100644 --- a/Zend/tests/020.phpt +++ b/Zend/tests/020.phpt @@ -3,9 +3,7 @@ func_get_arg() invalid usage --FILE-- <?php -var_dump(func_get_arg(1,2,3)); var_dump(func_get_arg(1)); -var_dump(func_get_arg()); function bar() { var_dump(func_get_arg(1)); @@ -20,15 +18,9 @@ foo(1,2); echo "Done\n"; ?> --EXPECTF-- -Warning: func_get_arg() expects exactly 1 parameter, 3 given in %s on line %d -NULL - Warning: func_get_arg(): Called from the global scope - no function context in %s on line %d bool(false) -Warning: func_get_arg() expects exactly 1 parameter, 0 given in %s on line %d -NULL - Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d bool(false) Done diff --git a/Zend/tests/024.phpt b/Zend/tests/024.phpt index 9e647d4231..d4e34972ee 100644 --- a/Zend/tests/024.phpt +++ b/Zend/tests/024.phpt @@ -15,43 +15,43 @@ var_dump($a->$b->{$c[1]}); ?> --EXPECTF-- -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d -Notice: Undefined variable: c in %s on line %d +Warning: Undefined variable: c in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d int(1) -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d -Notice: Undefined variable: b in %s on line %d +Warning: Undefined variable: b in %s on line %d int(0) -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d NULL -Notice: Undefined variable: b in %s on line %d +Warning: Undefined variable: b in %s on line %d int(1) -Notice: Trying to get property '1' of non-object in %s on line %d +Warning: Trying to get property '1' of non-object in %s on line %d NULL -Notice: Trying to get property '1' of non-object in %s on line %d +Warning: Trying to get property '1' of non-object in %s on line %d NULL -Notice: Undefined variable: c in %s on line %d +Warning: Undefined variable: c in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to get property '1' of non-object in %s on line %d +Warning: Trying to get property '1' of non-object in %s on line %d -Notice: Trying to get property '' of non-object in %s on line %d +Warning: Trying to get property '' of non-object in %s on line %d NULL diff --git a/Zend/tests/026.phpt b/Zend/tests/026.phpt index b3088e8473..0524487c5f 100644 --- a/Zend/tests/026.phpt +++ b/Zend/tests/026.phpt @@ -13,13 +13,16 @@ $test = new foo; $test->a()->a; print "ok\n"; -$test->a()->a = 1; +try { + $test->a()->a = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} print "ok\n"; ?> --EXPECTF-- -Notice: Trying to get property 'a' of non-object in %s on line %d +Warning: Trying to get property 'a' of non-object in %s on line %d ok - -Warning: Creating default object from empty value in %s on line %d +Attempt to assign property 'a' of non-object ok diff --git a/Zend/tests/033.phpt b/Zend/tests/033.phpt index 1e7fca1e0d..652db2de20 100644 --- a/Zend/tests/033.phpt +++ b/Zend/tests/033.phpt @@ -9,52 +9,58 @@ echo $arr[1][2][3][4][5]; $arr[1][2][3][4][5]->foo; -$arr[1][2][3][4][5]->foo = 1; +try { + $arr[1][2][3][4][5]->foo = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} $arr[][] = 2; -$arr[][]->bar = 2; +try { + $arr[][]->bar = 2; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECTF-- -Notice: Undefined variable: arr in %s on line %d +Warning: Undefined variable: arr in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Undefined variable: arr in %s on line %d +Warning: Undefined variable: arr in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Undefined variable: arr in %s on line %d +Warning: Undefined variable: arr in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to get property 'foo' of non-object in %s on line %d - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d +Warning: Trying to get property 'foo' of non-object in %s on line %d +Attempt to assign property 'foo' of non-object +Attempt to assign property 'bar' of non-object diff --git a/Zend/tests/036.phpt b/Zend/tests/036.phpt index 3ff522b16f..6b6549d935 100644 --- a/Zend/tests/036.phpt +++ b/Zend/tests/036.phpt @@ -3,14 +3,19 @@ Trying to use lambda in array offset --FILE-- <?php -$test[function(){}] = 1; -$a{function() { }} = 1; +try { + $test[function(){}] = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + $a{function() { }} = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECTF-- - -Deprecated: Array and string offset access syntax with curly braces is deprecated in %s line %d - -Warning: Illegal offset type in %s on line %d - -Warning: Illegal offset type in %s on line %d +Deprecated: Array and string offset access syntax with curly braces is deprecated in %s on line %d +Illegal offset type +Illegal offset type diff --git a/Zend/tests/038.phpt b/Zend/tests/038.phpt index 963e73f9ea..e55757bbcd 100644 --- a/Zend/tests/038.phpt +++ b/Zend/tests/038.phpt @@ -3,10 +3,12 @@ Trying to use lambda as array key --FILE-- <?php -var_dump(array(function() { } => 1)); +try { + var_dump(array(function() { } => 1)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- -Warning: Illegal offset type in %s on line %d -array(0) { -} +--EXPECT-- +Illegal offset type diff --git a/Zend/tests/anonymous_func_001.phpt b/Zend/tests/anonymous_func_001.phpt deleted file mode 100644 index 97b91b6544..0000000000 --- a/Zend/tests/anonymous_func_001.phpt +++ /dev/null @@ -1,54 +0,0 @@ ---TEST-- -Testing calls to anonymous function ---FILE-- -<?php - -for ($i = 0; $i < 10; $i++) { - $a = create_function('', 'return '. $i .';'); - var_dump($a()); - - $b = "\0lambda_". ($i + 1); - var_dump($b()); -} - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -int(0) -int(0) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(1) -int(1) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(2) -int(2) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(3) -int(3) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(4) -int(4) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(5) -int(5) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(6) -int(6) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(7) -int(7) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(8) -int(8) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(9) -int(9) diff --git a/Zend/tests/anonymous_func_002.phpt b/Zend/tests/anonymous_func_002.phpt deleted file mode 100644 index 28adc357da..0000000000 --- a/Zend/tests/anonymous_func_002.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -Testing anonymous function return as array key and accessing $GLOBALS ---FILE-- -<?php - -$test = create_function('$v', 'return $v;'); - -$arr = array(create_function('', 'return $GLOBALS["arr"];'), 2); - -var_dump($arr[$test(1)]); -var_dump($arr[$test(0)]() == $arr); - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d - -Deprecated: Function create_function() is deprecated in %s on line %d -int(2) -bool(true) diff --git a/Zend/tests/anonymous_func_003.phpt b/Zend/tests/anonymous_func_003.phpt deleted file mode 100644 index d2610310f7..0000000000 --- a/Zend/tests/anonymous_func_003.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Using throw $var with anonymous function return ---FILE-- -<?php - -try { - $a = create_function('', 'return new Exception("test");'); - throw $a(); -} catch (Exception $e) { - var_dump($e->getMessage() == 'test'); -} - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -bool(true) diff --git a/Zend/tests/arg_unpack/invalid_type.phpt b/Zend/tests/arg_unpack/invalid_type.phpt index 1ef545558c..ad580c37ae 100644 --- a/Zend/tests/arg_unpack/invalid_type.phpt +++ b/Zend/tests/arg_unpack/invalid_type.phpt @@ -7,53 +7,37 @@ function test(...$args) { var_dump($args); } -test(...null); -test(...42); -test(...new stdClass); - -test(1, 2, 3, ..."foo", ...[4, 5]); -test(1, 2, 3, ...new StdClass, ...3.14, ...[4, 5]); - -?> ---EXPECTF-- -Warning: Only arrays and Traversables can be unpacked in %s on line %d -array(0) { +try { + test(...null); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } - -Warning: Only arrays and Traversables can be unpacked in %s on line %d -array(0) { +try { + test(...42); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } - -Warning: Only arrays and Traversables can be unpacked in %s on line %d -array(0) { +try { + test(...new stdClass); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -Warning: Only arrays and Traversables can be unpacked in %s on line %d -array(5) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) - [4]=> - int(5) +try { + test(1, 2, 3, ..."foo", ...[4, 5]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } - -Warning: Only arrays and Traversables can be unpacked in %s on line %d - -Warning: Only arrays and Traversables can be unpacked in %s on line %d -array(5) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) - [4]=> - int(5) +try { + test(1, 2, 3, ...new StdClass, ...3.14, ...[4, 5]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } + +?> +--EXPECT-- +Only arrays and Traversables can be unpacked +Only arrays and Traversables can be unpacked +Only arrays and Traversables can be unpacked +Only arrays and Traversables can be unpacked +Only arrays and Traversables can be unpacked diff --git a/Zend/tests/argument_restriction_001.phpt b/Zend/tests/argument_restriction_001.phpt index 9c21dc2cce..2cd527f4fa 100644 --- a/Zend/tests/argument_restriction_001.phpt +++ b/Zend/tests/argument_restriction_001.phpt @@ -13,4 +13,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Warning: Declaration of & Sub::test() should be compatible with & Base::test($foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_001.php on line %d +Fatal error: Declaration of & Sub::test() must be compatible with & Base::test($foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_001.php on line %d diff --git a/Zend/tests/argument_restriction_002.phpt b/Zend/tests/argument_restriction_002.phpt index 4deb2d206b..511e4d3332 100644 --- a/Zend/tests/argument_restriction_002.phpt +++ b/Zend/tests/argument_restriction_002.phpt @@ -13,4 +13,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Warning: Declaration of Sub::test($foo, array &$bar) should be compatible with Base::test($foo, array &$bar, $option = NULL, $extra = 3.1415926535898) in %sargument_restriction_002.php on line %d +Fatal error: Declaration of Sub::test($foo, array &$bar) must be compatible with Base::test($foo, array &$bar, $option = NULL, $extra = 3.1415926535898) in %sargument_restriction_002.php on line %d diff --git a/Zend/tests/argument_restriction_003.phpt b/Zend/tests/argument_restriction_003.phpt index c24e0ba852..fb602194bb 100644 --- a/Zend/tests/argument_restriction_003.phpt +++ b/Zend/tests/argument_restriction_003.phpt @@ -16,4 +16,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Warning: Declaration of Sub::test() should be compatible with Base::test(Foo $foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_003.php on line %d +Fatal error: Declaration of Sub::test() must be compatible with Base::test(Foo $foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_003.php on line %d diff --git a/Zend/tests/argument_restriction_006.phpt b/Zend/tests/argument_restriction_006.phpt index 2df0e1e90d..788670cd51 100644 --- a/Zend/tests/argument_restriction_006.phpt +++ b/Zend/tests/argument_restriction_006.phpt @@ -13,4 +13,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Warning: Declaration of Sub::test($foo, $extra) should be compatible with Base::test($foo, $extra = Array) in %sargument_restriction_006.php on line %d +Fatal error: Declaration of Sub::test($foo, $extra) must be compatible with Base::test($foo, $extra = Array) in %sargument_restriction_006.php on line %d diff --git a/Zend/tests/array_literal_next_element_error.phpt b/Zend/tests/array_literal_next_element_error.phpt index 8b4af3cadd..23dec5e22c 100644 --- a/Zend/tests/array_literal_next_element_error.phpt +++ b/Zend/tests/array_literal_next_element_error.phpt @@ -4,22 +4,21 @@ Next free element may overflow in array literals <?php $i = PHP_INT_MAX; -$array = [$i => 42, new stdClass]; -var_dump($array); - -const FOO = [PHP_INT_MAX => 42, "foo"]; -var_dump(FOO); - -?> ---EXPECTF-- -Warning: Cannot add element to the array as the next element is already occupied in %s on line %d -array(1) { - [%d]=> - int(42) +try { + $array = [$i => 42, new stdClass]; + var_dump($array); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -Warning: Cannot add element to the array as the next element is already occupied in %s on line %d -array(1) { - [%d]=> - int(42) +function test($x = [PHP_INT_MAX => 42, "foo"]) {} +try { + test(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } + +?> +--EXPECT-- +Cannot add element to the array as the next element is already occupied +Cannot add element to the array as the next element is already occupied diff --git a/Zend/tests/array_offset.phpt b/Zend/tests/array_offset.phpt index 0879f80918..0a86bf7e9c 100644 --- a/Zend/tests/array_offset.phpt +++ b/Zend/tests/array_offset.phpt @@ -1,5 +1,5 @@ --TEST-- -Ensure "undefined offset" notice formats message corectly when undefined key is negative +Ensure "undefined offset" notice formats message correctly when undefined key is negative --FILE-- <?php diff --git a/Zend/tests/array_unpack/already_occupied.phpt b/Zend/tests/array_unpack/already_occupied.phpt index 27a18b6ced..b2febe0021 100644 --- a/Zend/tests/array_unpack/already_occupied.phpt +++ b/Zend/tests/array_unpack/already_occupied.phpt @@ -6,36 +6,28 @@ Appending to an array via unpack may fail <?php $arr = [1, 2, 3]; -var_dump([PHP_INT_MAX-1 => 0, ...$arr]); - -var_dump([PHP_INT_MAX-1 => 0, ...[1, 2, 3]]); - -const ARR = [1, 2, 3]; -const ARR2 = [PHP_INT_MAX-1 => 0, ...ARR]; -var_dump(ARR2); - -?> ---EXPECTF-- -Warning: Cannot add element to the array as the next element is already occupied in %s on line %d -array(2) { - [9223372036854775806]=> - int(0) - [9223372036854775807]=> - int(1) +try { + var_dump([PHP_INT_MAX-1 => 0, ...$arr]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -Warning: Cannot add element to the array as the next element is already occupied in %s on line %d -array(2) { - [9223372036854775806]=> - int(0) - [9223372036854775807]=> - int(1) +try { + var_dump([PHP_INT_MAX-1 => 0, ...[1, 2, 3]]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -Warning: Cannot add element to the array as the next element is already occupied in %s on line %d -array(2) { - [9223372036854775806]=> - int(0) - [9223372036854775807]=> - int(1) +const ARR = [1, 2, 3]; +function test($x = [PHP_INT_MAX-1 => 0, ...ARR]) {} +try { + test(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } + +?> +--EXPECT-- +Cannot add element to the array as the next element is already occupied +Cannot add element to the array as the next element is already occupied +Cannot add element to the array as the next element is already occupied diff --git a/Zend/tests/array_unpack/undef_var.phpt b/Zend/tests/array_unpack/undef_var.phpt index fff1f6171e..945717db76 100644 --- a/Zend/tests/array_unpack/undef_var.phpt +++ b/Zend/tests/array_unpack/undef_var.phpt @@ -6,9 +6,9 @@ array unpacking with undefinded variable var_dump([...$arr]); --EXPECTF-- -Notice: Undefined variable: arr in %s on line %d +Warning: Undefined variable: arr in %s on line %d Fatal error: Uncaught Error: Only arrays and Traversables can be unpacked in %s:%d Stack trace: #0 {main} - thrown in %s on line %d
\ No newline at end of file + thrown in %s on line %d diff --git a/Zend/tests/arrow_functions/002.phpt b/Zend/tests/arrow_functions/002.phpt index 52c8020c19..76254fc69a 100644 --- a/Zend/tests/arrow_functions/002.phpt +++ b/Zend/tests/arrow_functions/002.phpt @@ -9,5 +9,5 @@ var_dump((fn() => $b + $c)()); ?> --EXPECTF-- -Notice: Undefined variable: c in %s on line %d +Warning: Undefined variable: c in %s on line %d int(1) diff --git a/Zend/tests/arrow_functions/003.phpt b/Zend/tests/arrow_functions/003.phpt index 5e77743fad..4e6998c9d1 100644 --- a/Zend/tests/arrow_functions/003.phpt +++ b/Zend/tests/arrow_functions/003.phpt @@ -14,8 +14,8 @@ var_dump($fn()); ?> --EXPECTF-- -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d NULL -Notice: Undefined variable: 5 in %s on line %d +Warning: Undefined variable: 5 in %s on line %d NULL diff --git a/Zend/tests/assert/bug70208.phpt b/Zend/tests/assert/bug70208.phpt deleted file mode 100644 index 6b7dfaeb33..0000000000 --- a/Zend/tests/assert/bug70208.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Bug #70208 (scope information must be preserved with assert()) ---FILE-- -<?php - -function non_class_scope() { - return true; -} - -class test { - protected $prop = 1; - - public function __construct() { - assert('non_class_scope();'); - var_dump($this->prop); - } -} - -new test; - -?> ---EXPECTF-- -Deprecated: assert(): Calling assert() with a string argument is deprecated in %s on line %d -int(1) diff --git a/Zend/tests/assert/expect_015.phpt b/Zend/tests/assert/expect_015.phpt index 7f8b0a0935..5d172649af 100644 --- a/Zend/tests/assert/expect_015.phpt +++ b/Zend/tests/assert/expect_015.phpt @@ -62,7 +62,7 @@ assert(0 && ($a = function &(array &$a, ?X $b = null) use ($c,&$d) : ?X { } })); -assert(0 && ($a = function &(array &$a, X $b = null) use ($c,&$d) : X { +assert(0 && ($a = function &(array &$a, X $b = null, int|float $c) use ($c,&$d) : X { final class A { final protected function f2() { if (!$x) { @@ -204,7 +204,7 @@ Warning: assert(): assert(0 && ($a = function &(array &$a, ?X $b = null) use($c, })) failed in %sexpect_015.php on line %d -Warning: assert(): assert(0 && ($a = function &(array &$a, X $b = null) use($c, &$d): X { +Warning: assert(): assert(0 && ($a = function &(array &$a, X $b = null, int|float $c) use($c, &$d): X { final class A { protected final function f2() { if (!$x) { diff --git a/Zend/tests/assert/indirect_var_access_misoptimization.phpt b/Zend/tests/assert/indirect_var_access_misoptimization.phpt deleted file mode 100644 index 02327f30c0..0000000000 --- a/Zend/tests/assert/indirect_var_access_misoptimization.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Misoptimization when variable is modified by assert() ---INI-- -zend.assertions=1 ---FILE-- -<?php - -function test() { - $i = 0; - assert('$i = new stdClass'); - $i += 1; - var_dump($i); -} -test(); - -?> ---EXPECTF-- -Deprecated: assert(): Calling assert() with a string argument is deprecated in %s on line %d - -Notice: Object of class stdClass could not be converted to number in %s on line %d -int(2) diff --git a/Zend/tests/assign_dim_obj_null_return.phpt b/Zend/tests/assign_dim_obj_null_return.phpt index cff877fd8f..1641992a0c 100644 --- a/Zend/tests/assign_dim_obj_null_return.phpt +++ b/Zend/tests/assign_dim_obj_null_return.phpt @@ -7,50 +7,77 @@ function test() { $array = [PHP_INT_MAX => 42]; $true = true; - var_dump($array[] = 123); - var_dump($array[[]] = 123); - var_dump($array[new stdClass] = 123); - var_dump($true[123] = 456); - - var_dump($array[] += 123); - var_dump($array[[]] += 123); - var_dump($array[new stdClass] += 123); - var_dump($true[123] += 456); - - var_dump($true->foo = 123); - var_dump($true->foo += 123); -} - -test(); + try { + var_dump($array[] = 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -?> ---EXPECTF-- -Warning: Cannot add element to the array as the next element is already occupied in %s on line %d -NULL + try { + var_dump($array[[]] = 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -Warning: Illegal offset type in %s on line %d -NULL + try { + var_dump($array[new stdClass] = 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -Warning: Illegal offset type in %s on line %d -NULL + try { + var_dump($true[123] = 456); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -Warning: Cannot use a scalar value as an array in %s on line %d -NULL + try { + var_dump($array[] += 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -Warning: Cannot add element to the array as the next element is already occupied in %s on line %d -NULL + try { + var_dump($array[[]] += 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -Warning: Illegal offset type in %s on line %d -NULL + try { + var_dump($array[new stdClass] += 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -Warning: Illegal offset type in %s on line %d -NULL + try { + var_dump($true[123] += 456); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } -Warning: Cannot use a scalar value as an array in %s on line %d -NULL + try { + var_dump($true->foo = 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + try { + var_dump($true->foo += 123); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } +} -Warning: Attempt to assign property 'foo' of non-object in %s on line %d -NULL +test(); -Warning: Attempt to assign property 'foo' of non-object in %s on line %d -NULL +?> +--EXPECT-- +Cannot add element to the array as the next element is already occupied +Illegal offset type +Illegal offset type +Cannot use a scalar value as an array +Cannot add element to the array as the next element is already occupied +Illegal offset type +Illegal offset type +Cannot use a scalar value as an array +Attempt to assign property 'foo' of non-object +Attempt to assign property 'foo' of non-object diff --git a/Zend/tests/assign_ref_error_var_handling.phpt b/Zend/tests/assign_ref_error_var_handling.phpt index 5ecb577ba7..2a66b68cc5 100644 --- a/Zend/tests/assign_ref_error_var_handling.phpt +++ b/Zend/tests/assign_ref_error_var_handling.phpt @@ -7,19 +7,24 @@ function val() { return 42; } -$str = "foo"; $var = 24; -var_dump($str->foo =& $var); -var_dump($str); -var_dump($str->foo =& val()); -var_dump($str); +$arr = [PHP_INT_MAX => "foo"]; +try { + var_dump($arr[] =& $var); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump(count($arr)); +try { + var_dump($arr[] =& val()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump(count($arr)); ?> ---EXPECTF-- -Warning: Attempt to modify property 'foo' of non-object in %s on line %d -NULL -string(3) "foo" - -Warning: Attempt to modify property 'foo' of non-object in %s on line %d -NULL -string(3) "foo" +--EXPECT-- +Cannot add element to the array as the next element is already occupied +int(1) +Cannot add element to the array as the next element is already occupied +int(1) diff --git a/Zend/tests/assign_to_var_003.phpt b/Zend/tests/assign_to_var_003.phpt index bbe1b372bb..3ecf89e172 100644 --- a/Zend/tests/assign_to_var_003.phpt +++ b/Zend/tests/assign_to_var_003.phpt @@ -13,7 +13,7 @@ var_dump($var1); echo "Done\n"; ?> --EXPECTF-- -Notice: Trying to access array offset on value of type float in %s on line %d +Warning: Trying to access array offset on value of type float in %s on line %d NULL NULL Done diff --git a/Zend/tests/bug26166.phpt b/Zend/tests/bug26166.phpt index 7a3be86c3f..bd16050a87 100644 --- a/Zend/tests/bug26166.phpt +++ b/Zend/tests/bug26166.phpt @@ -61,11 +61,9 @@ try { } ?> -===DONE=== --EXPECT-- Hello World! ===NONE=== Method NoneTest::__toString() must return a string value ===THROW=== This is an error! -===DONE=== diff --git a/Zend/tests/bug26229.phpt b/Zend/tests/bug26229.phpt index cf23f157f8..393b49f3d0 100644 --- a/Zend/tests/bug26229.phpt +++ b/Zend/tests/bug26229.phpt @@ -23,7 +23,5 @@ catch(Exception $e) echo $e->getMessage() . "\n"; } ?> -===DONE=== --EXPECT-- Objects returned by array_iterator::getIterator() must be traversable or implement interface Iterator -===DONE=== diff --git a/Zend/tests/bug26696.phpt b/Zend/tests/bug26696.phpt index 14083dfb9f..57ba310c1d 100644 --- a/Zend/tests/bug26696.phpt +++ b/Zend/tests/bug26696.phpt @@ -16,7 +16,5 @@ for ($i = 0; $i < $len; $i++) { } ?> -===DONE=== --EXPECT-- a-s-d-d-/-?+ -===DONE=== diff --git a/Zend/tests/bug26697.phpt b/Zend/tests/bug26697.phpt index fe269c0364..1692e388ef 100644 --- a/Zend/tests/bug26697.phpt +++ b/Zend/tests/bug26697.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #26697 (calling class_exists on a nonexistent class in __autoload results in segfault) +Bug #26697 (calling class_exists on a nonexistent class in autoloader results in segfault) --FILE-- <?php @@ -12,10 +12,8 @@ spl_autoload_register(function ($name) { var_dump(class_exists('NotExistingClass')); ?> -===DONE=== --EXPECT-- {closure}(NotExistingClass) bool(false) {closure}(NotExistingClass), done bool(false) -===DONE=== diff --git a/Zend/tests/bug26698.phpt b/Zend/tests/bug26698.phpt index 8fbf551b6b..066fdc3a37 100644 --- a/Zend/tests/bug26698.phpt +++ b/Zend/tests/bug26698.phpt @@ -65,9 +65,7 @@ $p->callOne(); $p->callTwo(); $p->callThree(); ?> -===DONE=== --EXPECT-- Caught: NONE Caught: NONE Caught: NONE -===DONE=== diff --git a/Zend/tests/bug26802.phpt b/Zend/tests/bug26802.phpt index 0ab4760d48..11e468d088 100644 --- a/Zend/tests/bug26802.phpt +++ b/Zend/tests/bug26802.phpt @@ -30,8 +30,6 @@ foo::$method(); ?> -===DONE=== --EXPECT-- global_func foo::foo_func -===DONE=== diff --git a/Zend/tests/bug27304.phpt b/Zend/tests/bug27304.phpt index 9eb1ececf7..f9ca3e2ecf 100644 --- a/Zend/tests/bug27304.phpt +++ b/Zend/tests/bug27304.phpt @@ -16,8 +16,6 @@ Staticexample::test(); $b->test(); ?> -===DONE=== --EXPECT-- bool(false) bool(false) -===DONE=== diff --git a/Zend/tests/bug27669.phpt b/Zend/tests/bug27669.phpt index 97b15590e2..679c7a6105 100644 --- a/Zend/tests/bug27669.phpt +++ b/Zend/tests/bug27669.phpt @@ -3,15 +3,12 @@ Bug #27669 (PHP 5 didn't support all possibilities for calling static methods dy --FILE-- <?php class A { - function hello() { + static function hello() { echo "Hello World\n"; } } $y[0] = 'hello'; A::{$y[0]}(); ?> -===DONE=== --EXPECTF-- -Deprecated: Non-static method A::hello() should not be called statically in %s on line %d Hello World -===DONE=== diff --git a/Zend/tests/bug27798.phpt b/Zend/tests/bug27798.phpt index 2545d9e100..9c84731fe6 100644 --- a/Zend/tests/bug27798.phpt +++ b/Zend/tests/bug27798.phpt @@ -32,7 +32,6 @@ var_dump(get_object_vars(new Base)); var_dump(get_object_vars(new Child)); ?> -===DONE=== --EXPECT-- Base::__construct array(3) { @@ -69,4 +68,3 @@ array(1) { ["Foo"]=> int(1) } -===DONE=== diff --git a/Zend/tests/bug28442.phpt b/Zend/tests/bug28442.phpt index 36a6fc6ab9..fd57fef854 100644 --- a/Zend/tests/bug28442.phpt +++ b/Zend/tests/bug28442.phpt @@ -44,7 +44,6 @@ var_dump(ClassB::$prop); var_dump(ClassC::$prop); ?> -===DONE=== --EXPECT-- ===INIT=== string(1) "A" @@ -62,4 +61,3 @@ string(2) "B2" string(2) "A2" string(2) "C2" string(2) "C2" -===DONE=== diff --git a/Zend/tests/bug28444.phpt b/Zend/tests/bug28444.phpt index 464aaef4c7..245a1f2704 100644 --- a/Zend/tests/bug28444.phpt +++ b/Zend/tests/bug28444.phpt @@ -52,7 +52,6 @@ var_dump($t->x = 5); var_dump($y->z->x = 6); ?> -===DONE=== --EXPECT-- object(ObjectOne)#2 (1) { ["x"]=> @@ -75,4 +74,3 @@ Overloaded::__get(z) int(5) Overloaded::__get(z) int(6) -===DONE=== diff --git a/Zend/tests/bug29368.phpt b/Zend/tests/bug29368.phpt index 1987fa9b45..20dc59a644 100644 --- a/Zend/tests/bug29368.phpt +++ b/Zend/tests/bug29368.phpt @@ -27,8 +27,6 @@ try unset($bar); ?> -===DONE=== --EXPECT-- Foo::__construct Caught exception! -===DONE=== diff --git a/Zend/tests/bug29505.phpt b/Zend/tests/bug29505.phpt index 4d7c053516..a52ea66929 100644 --- a/Zend/tests/bug29505.phpt +++ b/Zend/tests/bug29505.phpt @@ -11,7 +11,6 @@ class Test { var_dump(get_class_vars('Test')); ?> -===DONE=== --EXPECT-- array(2) { ["empty"]=> @@ -28,4 +27,3 @@ array(2) { } } } -===DONE=== diff --git a/Zend/tests/bug29674.phpt b/Zend/tests/bug29674.phpt index 60f08a6df2..f1706cabb7 100644 --- a/Zend/tests/bug29674.phpt +++ b/Zend/tests/bug29674.phpt @@ -33,7 +33,7 @@ $obj->printVars(); ===BASE=== string(4) "Base" -Notice: Undefined property: BaseClass::$private_child in %sbug29674.php on line %d +Warning: Undefined property: BaseClass::$private_child in %s on line %d NULL ===CHILD=== string(4) "Base" diff --git a/Zend/tests/bug29689.phpt b/Zend/tests/bug29689.phpt index 12b3430089..16f80440d4 100644 --- a/Zend/tests/bug29689.phpt +++ b/Zend/tests/bug29689.phpt @@ -52,7 +52,7 @@ $baz->printFoo(); --EXPECTF-- foo: foo foo2 bar: bar -Notice: Undefined property: bar::$foo2 in %s on line %d +Warning: Undefined property: bar::$foo2 in %s on line %d ---baz-- foo: foo foo2 diff --git a/Zend/tests/bug29883.phpt b/Zend/tests/bug29883.phpt index 4e07b02d10..d9e1ae43b1 100644 --- a/Zend/tests/bug29883.phpt +++ b/Zend/tests/bug29883.phpt @@ -15,7 +15,7 @@ bool(false) bool(true) bool(true) -Notice: Uninitialized string offset: -10 in %s on line 6 +Warning: Uninitialized string offset: -10 in %s on line %d string(0) "" string(1) "u" string(1) "u" diff --git a/Zend/tests/bug29890.phpt b/Zend/tests/bug29890.phpt index 1fdcdc4291..6f1e874882 100644 --- a/Zend/tests/bug29890.phpt +++ b/Zend/tests/bug29890.phpt @@ -2,7 +2,7 @@ Bug #29890 (crash if error handler fails) --FILE-- <?php -function customErrorHandler($fErrNo,$fErrStr,$fErrFile,$fErrLine,$fClass) { +function customErrorHandler($fErrNo,$fErrStr,$fErrFile,$fErrLine) { echo "error :".$fErrStr."\n"; } diff --git a/Zend/tests/bug29896.phpt b/Zend/tests/bug29896.phpt index 35a92d459c..6b96ac4704 100644 --- a/Zend/tests/bug29896.phpt +++ b/Zend/tests/bug29896.phpt @@ -2,7 +2,7 @@ Bug #29896 (Backtrace argument list out of sync) --FILE-- <?php -function userErrorHandler($num, $msg, $file, $line, $vars) +function userErrorHandler($num, $msg, $file, $line) { debug_print_backtrace(); } @@ -22,6 +22,6 @@ function GenerateError2($A1) GenerateError2("Test2"); ?> --EXPECTF-- -#0 userErrorHandler(8, Undefined variable: b, %sbug29896.php, 11, Array ([A1] => Test1)) called at [%sbug29896.php:11] +#0 userErrorHandler(2, Undefined variable: b, %s, %d) called at [%s:%d] #1 GenerateError1(Test1) called at [%sbug29896.php:16] #2 GenerateError2(Test2) called at [%sbug29896.php:19] diff --git a/Zend/tests/bug30162.phpt b/Zend/tests/bug30162.phpt index 55d26a3e3a..4b2739ab2e 100644 --- a/Zend/tests/bug30162.phpt +++ b/Zend/tests/bug30162.phpt @@ -41,9 +41,8 @@ $db = new hariCow; var_dump($db); ?> -===DONE=== --EXPECTF-- -Notice: Undefined variable: db in %sbug30162.php on line 35 +Warning: Undefined variable: db in %s on line %d NULL object(hariCow)#%d (2) { ["x"]=> @@ -51,4 +50,3 @@ object(hariCow)#%d (2) { ["y"]=> string(1) "y" } -===DONE=== diff --git a/Zend/tests/bug30346.phpt b/Zend/tests/bug30346.phpt index 8db080f820..3a4caa6f7a 100644 --- a/Zend/tests/bug30346.phpt +++ b/Zend/tests/bug30346.phpt @@ -18,7 +18,5 @@ echo $post[$id.'_show']; echo "\n"; ?> -===DONE=== --EXPECT-- page_show -===DONE=== diff --git a/Zend/tests/bug30407.phpt b/Zend/tests/bug30407.phpt index 6dcc6b3481..ad1993897d 100644 --- a/Zend/tests/bug30407.phpt +++ b/Zend/tests/bug30407.phpt @@ -11,8 +11,6 @@ function haricow($a = 'one') { haricow(); haricow(); ?> -===DONE=== --EXPECT-- string(3) "one" string(3) "one" -===DONE=== diff --git a/Zend/tests/bug30725.phpt b/Zend/tests/bug30725.phpt index 75cb04843c..bbcf09dfdd 100644 --- a/Zend/tests/bug30725.phpt +++ b/Zend/tests/bug30725.phpt @@ -26,7 +26,5 @@ catch(Exception $e) } ?> -===DONE=== --EXPECT-- Caught -===DONE=== diff --git a/Zend/tests/bug30998.phpt b/Zend/tests/bug30998.phpt index 2ff3068e5c..310c08d75f 100644 --- a/Zend/tests/bug30998.phpt +++ b/Zend/tests/bug30998.phpt @@ -13,9 +13,7 @@ set_error_handler('my_error'); $f = fopen("/tmp/blah", "r"); ?> -===DONE=== --EXPECTF-- fopen(/tmp/blah): failed to open stream: %s (2) in %s:%d Warning: fopen(/tmp/blah): failed to open stream: %s in %s on line %d -===DONE=== diff --git a/Zend/tests/bug31098.phpt b/Zend/tests/bug31098.phpt index 1849528231..3276782c01 100644 --- a/Zend/tests/bug31098.phpt +++ b/Zend/tests/bug31098.phpt @@ -44,7 +44,7 @@ ok ok ok -Notice: Trying to get property 'wrong' of non-object in %s on line %d +Warning: Trying to get property 'wrong' of non-object in %s on line %d ok Warning: Illegal string offset 'wrong' in %s on line %d diff --git a/Zend/tests/bug31102.phpt b/Zend/tests/bug31102.phpt index fd6da0f7c2..c01c2e004a 100644 --- a/Zend/tests/bug31102.phpt +++ b/Zend/tests/bug31102.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #31102 (Exception not handled when thrown inside __autoload()) +Bug #31102 (Exception not handled when thrown inside autoloader) --FILE-- <?php @@ -36,7 +36,6 @@ while($test++ < 5) } ?> ===DONE=== -<?php exit(0); ?> --EXPECTF-- {closure}(Test1,1) Caught: Test1::__construct diff --git a/Zend/tests/bug31720.phpt b/Zend/tests/bug31720.phpt index c4680a4789..1e01d41772 100644 --- a/Zend/tests/bug31720.phpt +++ b/Zend/tests/bug31720.phpt @@ -4,11 +4,12 @@ Bug #31720 (Invalid object callbacks not caught in array_walk()) <?php $array = array('at least one element'); -array_walk($array, array($nonesuchvar,'show')); +try { + array_walk($array, array($nonesuchvar,'show')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> -===DONE=== --EXPECTF-- -Notice: Undefined variable: nonesuchvar in %s on line %d - -Warning: array_walk() expects parameter 2 to be a valid callback, first array member is not a valid class name or object in %s on line %d -===DONE=== +Warning: Undefined variable: nonesuchvar in %s on line %d +array_walk() expects parameter 2 to be a valid callback, first array member is not a valid class name or object diff --git a/Zend/tests/bug32226.phpt b/Zend/tests/bug32226.phpt index f8e13cfb6e..d3432c4247 100644 --- a/Zend/tests/bug32226.phpt +++ b/Zend/tests/bug32226.phpt @@ -30,7 +30,5 @@ catch(Exception $e) } ?> -===DONE=== --EXPECT-- Caught -===DONE=== diff --git a/Zend/tests/bug32252.phpt b/Zend/tests/bug32252.phpt index 706da18cfb..ce97384c0e 100644 --- a/Zend/tests/bug32252.phpt +++ b/Zend/tests/bug32252.phpt @@ -40,8 +40,6 @@ catch (Exception $e) } ?> -===DONE=== --EXPECT-- Test::offsetSet(-1, 123) CAUGHT -===DONE=== diff --git a/Zend/tests/bug32290.phpt b/Zend/tests/bug32290.phpt index e73bca12ac..a58bcf4ce3 100644 --- a/Zend/tests/bug32290.phpt +++ b/Zend/tests/bug32290.phpt @@ -94,8 +94,6 @@ echo "\n===E===\n"; var_dump($x->doSomethingStatic(1)); ?> -===DONE=== -<?php exit(0); ?> --EXPECT-- ===A=== TestB::doSomething(1) @@ -121,4 +119,3 @@ int(1) TestB::doSomethingStatic(1) TestA::doSomethingStatic(2) int(1) -===DONE=== diff --git a/Zend/tests/bug33116.phpt b/Zend/tests/bug33116.phpt index 13aae6611e..b336171165 100644 --- a/Zend/tests/bug33116.phpt +++ b/Zend/tests/bug33116.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #33116 (crash when assigning class name to global variable in __autoload) +Bug #33116 (crash when assigning class name to global variable in autoloader) --FILE-- <?php spl_autoload_register(function ($class) { diff --git a/Zend/tests/bug34786.phpt b/Zend/tests/bug34786.phpt index 18642848d8..ef0627633f 100644 --- a/Zend/tests/bug34786.phpt +++ b/Zend/tests/bug34786.phpt @@ -10,13 +10,13 @@ function bar() { echo "bar: ".error_reporting()."\n"; } -error_reporting(1); +error_reporting(E_WARNING); echo "before: ".error_reporting()."\n"; @foo(1,@bar(),3); echo "after: ".error_reporting()."\n"; ?> --EXPECT-- -before: 1 +before: 2 bar: 0 foo: 0 -after: 1 +after: 2 diff --git a/Zend/tests/bug35017.phpt b/Zend/tests/bug35017.phpt index 9944df55e0..8a747be7e1 100644 --- a/Zend/tests/bug35017.phpt +++ b/Zend/tests/bug35017.phpt @@ -13,7 +13,7 @@ try { } catch(Exception $e) { echo "This Exception should be caught\n"; } -function errorHandler($errno, $errstr, $errfile, $errline, $vars) { +function errorHandler($errno, $errstr, $errfile, $errline) { throw new Exception('Some Exception'); } ?> diff --git a/Zend/tests/bug35437.phpt b/Zend/tests/bug35437.phpt deleted file mode 100644 index 4f61e4fbfd..0000000000 --- a/Zend/tests/bug35437.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Bug #35437 (Segfault or Invalid Opcode 137/1/4) ---FILE-- -<?php -function err2exception($errno, $errstr) -{ - throw new Exception("Error occuried: " . $errstr); -} - -set_error_handler('err2exception'); - -class TestClass -{ - function testMethod() - { - $GLOBALS['t'] = new stdClass; - } -} - -try { - TestClass::testMethod(); -} catch (Exception $e) { - echo "Caught: ".$e->getMessage()."\n"; -} -?> ---EXPECT-- -Caught: Error occuried: Non-static method TestClass::testMethod() should not be called statically diff --git a/Zend/tests/bug36268.phpt b/Zend/tests/bug36268.phpt index 8c93186c73..3bec61ff49 100644 --- a/Zend/tests/bug36268.phpt +++ b/Zend/tests/bug36268.phpt @@ -15,3 +15,4 @@ Fatal error: Uncaught Error: Call to undefined function bar() in %sbug36268.php: Stack trace: #0 {main} thrown in %sbug36268.php on line 8 +Ha! diff --git a/Zend/tests/bug36303.phpt b/Zend/tests/bug36303.phpt deleted file mode 100644 index 3ea036a838..0000000000 --- a/Zend/tests/bug36303.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -Bug #36303 (foreach on error_zval produces segfault) ---FILE-- -<?php -$x="test"; -foreach($x->a->b as &$v) { -} -echo "ok\n"; -?> ---EXPECTF-- -Warning: Attempt to modify property 'a' of non-object in %sbug36303.php on line 3 - -Warning: Invalid argument supplied for foreach() in %sbug36303.php on line 3 -ok diff --git a/Zend/tests/bug37138.phpt b/Zend/tests/bug37138.phpt index 4a084d4bb1..c0aa1fdfa8 100644 --- a/Zend/tests/bug37138.phpt +++ b/Zend/tests/bug37138.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #37138 (__autoload tries to load callback'ed self and parent) +Bug #37138 (autoloader tries to load callback'ed self and parent) --FILE-- <?php spl_autoload_register(function ($CN) { var_dump ($CN); }); diff --git a/Zend/tests/bug37212.phpt b/Zend/tests/bug37212.phpt index 212ef23ec7..0d19efa8f1 100644 --- a/Zend/tests/bug37212.phpt +++ b/Zend/tests/bug37212.phpt @@ -38,7 +38,6 @@ $B->copyValue($C); var_dump($B); ?> -===DONE=== --EXPECTF-- object(B)#%d (1) { ["value":protected]=> @@ -52,4 +51,3 @@ object(B)#%d (1) { ["value":protected]=> string(1) "C" } -===DONE=== diff --git a/Zend/tests/bug37667.phpt b/Zend/tests/bug37667.phpt index ecf43c5b80..83a87a9688 100644 --- a/Zend/tests/bug37667.phpt +++ b/Zend/tests/bug37667.phpt @@ -26,7 +26,6 @@ $obj->property[] = 2; var_dump($obj); ?> -===DONE=== --EXPECTF-- string(3) "bar" @@ -50,4 +49,3 @@ object(Test)#%d (1) { string(3) "bar" } } -===DONE=== diff --git a/Zend/tests/bug37811.phpt b/Zend/tests/bug37811.phpt index 96645d0354..8321459d5d 100644 --- a/Zend/tests/bug37811.phpt +++ b/Zend/tests/bug37811.phpt @@ -23,6 +23,7 @@ string(3) "Foo" Warning: Constants may only evaluate to scalar values, arrays or resources in %sbug37811.php on line %d -Warning: Use of undefined constant Baz - assumed 'Baz' (this will throw an Error in a future version of PHP) in %sbug37811.php on line %d -string(3) "Baz" -===DONE=== +Fatal error: Uncaught Error: Undefined constant 'Baz' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug38047.phpt b/Zend/tests/bug38047.phpt deleted file mode 100644 index e6eeb6631d..0000000000 --- a/Zend/tests/bug38047.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -Bug #38047 ("file" and "line" sometimes not set in backtrace from inside error handler) ---FILE-- -<?php -error_reporting(E_ALL); -set_error_handler('kalus_error_handler'); -ini_set("display_errors", "on"); - -class A { - function A_ftk($a) { - } -} - -function kalus_error_handler($error_code, $error_string, $filename, $line, $symbols) { - echo "$error_string\n"; - get_error_context(); -} - -function get_error_context() { - $backtrace = debug_backtrace(); - $n = 1; - foreach ($backtrace as $call) { - echo $n++." "; - if (isset($call["file"])) { - echo $call["file"]; - if (isset($call["line"])) { - echo ":".$call["line"]; - } - } - if (isset($call["function"])) { - echo " ".$call["function"]."()"; - } - echo "\n"; - } - echo "\n"; -} - -//This will not create file and line items for the call into the error handler -$page["name"] = A::A_ftk(); -?> ---EXPECTF-- -Non-static method A::A_ftk() should not be called statically -1 %sbug38047.php:13 get_error_context() -2 %sbug38047.php:36 kalus_error_handler() - - -Fatal error: Uncaught ArgumentCountError: Too few arguments to function A::A_ftk(), 0 passed in %sbug38047.php on line 36 and exactly 1 expected in %sbug38047.php:7 -Stack trace: -#0 %sbug38047.php(36): A::A_ftk() -#1 {main} - thrown in %sbug38047.php on line 7 diff --git a/Zend/tests/bug38942.phpt b/Zend/tests/bug38942.phpt deleted file mode 100644 index d0335b1071..0000000000 --- a/Zend/tests/bug38942.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Bug #38942 (Double old-style-ctor inheritance) ---FILE-- -<?php -class foo { - public function foo() {} -} - -class bar extends foo { -} -print_r(get_class_methods("bar")); -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in %s on line %d -Array -( - [0] => foo -) diff --git a/Zend/tests/bug39003.phpt b/Zend/tests/bug39003.phpt index dc1c69e8c7..791e11b614 100644 --- a/Zend/tests/bug39003.phpt +++ b/Zend/tests/bug39003.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #39003 (__autoload() is called for type hinting) +Bug #39003 (autoloader is called for type hinting) --FILE-- <?php diff --git a/Zend/tests/bug39018.phpt b/Zend/tests/bug39018.phpt index a00e1fb819..43198b5c85 100644 --- a/Zend/tests/bug39018.phpt +++ b/Zend/tests/bug39018.phpt @@ -62,44 +62,44 @@ print "\nDone\n"; ?> --EXPECTF-- -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d -Notice: Uninitialized string offset: %s in %s on line 6 +Warning: Uninitialized string offset: %s in %s on line %d -Notice: Uninitialized string offset: 0 in %s on line %d +Warning: Uninitialized string offset: 0 in %s on line %d -Notice: Uninitialized string offset: 0 in %s on line %d +Warning: Uninitialized string offset: 0 in %s on line %d -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d -Notice: Uninitialized string offset: %i in %s on line %d +Warning: Uninitialized string offset: %i in %s on line %d -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d -Notice: Uninitialized string offset: %i in %s on line %d +Warning: Uninitialized string offset: %i in %s on line %d -Notice: Uninitialized string offset: 0 in %s on line %d +Warning: Uninitialized string offset: 0 in %s on line %d -Notice: Uninitialized string offset: 4 in %s on line %d +Warning: Uninitialized string offset: 4 in %s on line %d -Notice: Uninitialized string offset: 4 in %s on line %d +Warning: Uninitialized string offset: 4 in %s on line %d -Notice: Uninitialized string offset: 4 in %s on line %d +Warning: Uninitialized string offset: 4 in %s on line %d -Notice: Uninitialized string offset: 4 in %s on line %d +Warning: Uninitialized string offset: 4 in %s on line %d -Notice: Uninitialized string offset: 4 in %s on line %d +Warning: Uninitialized string offset: 4 in %s on line %d -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d -Notice: Uninitialized string offset: 12 in %s on line %d +Warning: Uninitialized string offset: 12 in %s on line %d -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d -Notice: Uninitialized string offset: 12 in %s on line %d +Warning: Uninitialized string offset: 12 in %s on line %d -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d b Done diff --git a/Zend/tests/bug39036.phpt b/Zend/tests/bug39036.phpt index 419810eaa1..0cdd75150d 100644 --- a/Zend/tests/bug39036.phpt +++ b/Zend/tests/bug39036.phpt @@ -14,6 +14,6 @@ var_dump($key); echo "Done\n"; ?> --EXPECTF-- -Notice: Undefined variable: key in %s on line %d +Warning: Undefined variable: key in %s on line %d NULL Done diff --git a/Zend/tests/bug39127.phpt b/Zend/tests/bug39127.phpt deleted file mode 100644 index 31fb6d27d5..0000000000 --- a/Zend/tests/bug39127.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Bug #39127 (Old-style constructor fallbacks produce strange results) ---FILE-- -<?php - -class a { function a() { var_dump("a::a() called"); } } -class b extends a {} - -$b = new b; -var_dump(is_callable(array($b,"a"))); -var_dump(is_callable(array($b,"b"))); -var_dump(is_callable(array($b,"__construct"))); - -echo "Done\n"; -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; a has a deprecated constructor in %s on line %d -string(13) "a::a() called" -bool(true) -bool(false) -bool(false) -Done diff --git a/Zend/tests/bug39304.phpt b/Zend/tests/bug39304.phpt index 4394cae1d4..dc31073eb9 100644 --- a/Zend/tests/bug39304.phpt +++ b/Zend/tests/bug39304.phpt @@ -7,6 +7,6 @@ Bug #39304 (Segmentation fault with list unpacking of string offset) var_dump($a,$b); ?> --EXPECTF-- -Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d +Warning: Uninitialized string offset: 0 in %s on line %d NULL NULL diff --git a/Zend/tests/bug40236.phpt b/Zend/tests/bug40236.phpt index 81cd56f71f..204b117099 100644 --- a/Zend/tests/bug40236.phpt +++ b/Zend/tests/bug40236.phpt @@ -2,7 +2,6 @@ Bug #40236 (php -a function allocation eats memory) --SKIPIF-- <?php -if (php_sapi_name() != "cli") die("skip CLI only"); if (extension_loaded("readline")) die("skip Test doesn't support readline"); ?> --FILE-- diff --git a/Zend/tests/bug40621.phpt b/Zend/tests/bug40621.phpt index b56a28e58b..8650fd56fa 100644 --- a/Zend/tests/bug40621.phpt +++ b/Zend/tests/bug40621.phpt @@ -15,10 +15,7 @@ Foo::get(); echo "Done\n"; ?> --EXPECTF-- -Deprecated: Non-static method Foo::get() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Non-static method Foo::__construct() cannot be called statically in %s:%d +Fatal error: Uncaught Error: Non-static method Foo::get() cannot be called statically in %s:%d Stack trace: -#0 %s(%d): Foo::get() -#1 {main} +#0 {main} thrown in %s on line %d diff --git a/Zend/tests/bug40784.phpt b/Zend/tests/bug40784.phpt deleted file mode 100644 index ac2b2331b2..0000000000 --- a/Zend/tests/bug40784.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -Bug #40784 (Case sensivity in constructor's fallback) ---FILE-- -<?php - -class A { - function A () { echo "I'm A\n"; } -} - -class B extends A { - function __construct() { - parent::__construct(); - parent::__constrUct(); - } -} - -$b = new B; - -echo "Done\n"; -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; A has a deprecated constructor in %s on line %d -I'm A -I'm A -Done diff --git a/Zend/tests/bug41075.phpt b/Zend/tests/bug41075.phpt deleted file mode 100644 index 03cf3a42f3..0000000000 --- a/Zend/tests/bug41075.phpt +++ /dev/null @@ -1,31 +0,0 @@ ---TEST-- -Bug #41075 (memleak when creating default object caused exception) ---FILE-- -<?php - -function err($errno, $errstr, $errfile, $errline) -{ - throw new Exception($errstr); -} - -set_error_handler("err"); - -class test { - function foo() { - $var = $this->blah->prop = "string"; - var_dump($this->blah); - } -} - -$t = new test; -try { - $t->foo(); -} catch (Exception $e) { - var_dump($e->getMessage()); -} - -echo "Done\n"; -?> ---EXPECT-- -string(40) "Creating default object from empty value" -Done diff --git a/Zend/tests/bug41209.phpt b/Zend/tests/bug41209.phpt index 3924f99ac8..da9f57163d 100644 --- a/Zend/tests/bug41209.phpt +++ b/Zend/tests/bug41209.phpt @@ -41,6 +41,6 @@ echo "Done\n"; --EXPECTF-- Fatal error: Uncaught ErrorException: Undefined variable: id in %s:%d Stack trace: -#0 %s(%d): env::errorHandler(8, '%s', '%s', 34, Array) +#0 %s(%d): env::errorHandler(2, 'Undefined varia...', '%s', %d) #1 {main} thrown in %s on line %d diff --git a/Zend/tests/bug43201.phpt b/Zend/tests/bug43201.phpt index 2ab26ca4b9..fa14b162d4 100644 --- a/Zend/tests/bug43201.phpt +++ b/Zend/tests/bug43201.phpt @@ -26,29 +26,29 @@ Notice: Indirect modification of overloaded property Foo::$arr has no effect in Notice: Indirect modification of overloaded property Foo::$arr has no effect in %sbug43201.php on line 14 -Notice: Undefined variable: ref in %sbug43201.php on line 14 +Warning: Undefined variable: ref in %s on line %d -Notice: Undefined variable: undef in %sbug43201.php on line 16 +Warning: Undefined variable: undef in %s on line %d Notice: Indirect modification of overloaded property Foo::$arr has no effect in %sbug43201.php on line 17 -Notice: Undefined variable: undef in %sbug43201.php on line 16 +Warning: Undefined variable: undef in %s on line %d Notice: Indirect modification of overloaded property Foo::$arr has no effect in %sbug43201.php on line 17 -Notice: Undefined variable: undef in %sbug43201.php on line 16 +Warning: Undefined variable: undef in %s on line %d Notice: Indirect modification of overloaded property Foo::$arr has no effect in %sbug43201.php on line 17 -Notice: Undefined variable: undef in %sbug43201.php on line 16 +Warning: Undefined variable: undef in %s on line %d Notice: Indirect modification of overloaded property Foo::$arr has no effect in %sbug43201.php on line 17 -Notice: Undefined variable: undef in %sbug43201.php on line 16 +Warning: Undefined variable: undef in %s on line %d Notice: Indirect modification of overloaded property Foo::$arr has no effect in %sbug43201.php on line 17 -Notice: Undefined variable: undef in %sbug43201.php on line 16 +Warning: Undefined variable: undef in %s on line %d Notice: Indirect modification of overloaded property Foo::$arr has no effect in %sbug43201.php on line 17 ok diff --git a/Zend/tests/bug43323.phpt b/Zend/tests/bug43323.phpt deleted file mode 100644 index 74abe766e5..0000000000 --- a/Zend/tests/bug43323.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -Bug #43323 (Wrong count abstract methods) ---FILE-- -<?php -abstract class bar { - abstract public function bar(); -} - -class foo extends bar { -} ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; bar has a deprecated constructor in %s on line %d - -Fatal error: Class foo contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (bar::bar) in %sbug43323.php on line 7 diff --git a/Zend/tests/bug43344_1.phpt b/Zend/tests/bug43344_1.phpt index 4635240699..28af70dc67 100644 --- a/Zend/tests/bug43344_1.phpt +++ b/Zend/tests/bug43344_1.phpt @@ -3,6 +3,8 @@ Bug #43344.1 (Wrong error message for undefined namespace constant) --FILE-- <?php namespace Foo; +use Error; + function f1($a=bar) { return $a; } @@ -13,20 +15,31 @@ function f3($a=array(bar=>0)) { reset($a); return key($a); } -echo bar."\n"; -echo f1()."\n"; -echo f2()."\n"; -echo f3()."\n"; -?> ---EXPECTF-- -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 13 -bar -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 3 -bar - -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 6 -bar +try { + echo bar."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + echo f1()."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + echo f2()."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + echo f3()."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 9 -bar +?> +--EXPECT-- +Undefined constant 'Foo\bar' +Undefined constant 'Foo\bar' +Undefined constant 'Foo\bar' +Undefined constant 'Foo\bar' diff --git a/Zend/tests/bug44660.phpt b/Zend/tests/bug44660.phpt index 980c2274cd..fbe4a90dcd 100644 --- a/Zend/tests/bug44660.phpt +++ b/Zend/tests/bug44660.phpt @@ -8,42 +8,62 @@ $a = true; echo "--> read access: "; echo $a->p; -echo "\n--> direct assignment: "; -$a->p = $s; +echo "\n--> direct assignment:\n"; +try { + $a->p = $s; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -echo "\n--> increment: "; -$a->p++; +echo "\n--> increment:\n"; +try { + $a->p++; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -echo "\n--> reference assignment:"; -$a->p =& $s; +echo "\n--> reference assignment:\n"; +try { + $a->p =& $s; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -echo "\n--> reference assignment:"; -$s =& $a->p; +echo "\n--> reference assignment:\n"; +try { + $s =& $a->p; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -echo "\n--> indexed assignment:"; -$a->p[0] = $s; +echo "\n--> indexed assignment:\n"; +try { + $a->p[0] = $s; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} echo "\n--> Confirm assignments have had no impact:\n"; var_dump($a); ?> --EXPECTF-- --> read access: -Notice: Trying to get property 'p' of non-object in %sbug44660.php on line 6 +Warning: Trying to get property 'p' of non-object in %s on line %d ---> direct assignment: -Warning: Attempt to assign property 'p' of non-object in %sbug44660.php on line 9 +--> direct assignment: +Attempt to assign property 'p' of non-object ---> increment: -Warning: Attempt to increment/decrement property 'p' of non-object in %sbug44660.php on line 12 +--> increment: +Attempt to increment/decrement property 'p' of non-object --> reference assignment: -Warning: Attempt to modify property 'p' of non-object in %sbug44660.php on line 15 +Attempt to modify property 'p' of non-object --> reference assignment: -Warning: Attempt to modify property 'p' of non-object in %sbug44660.php on line 18 +Attempt to modify property 'p' of non-object --> indexed assignment: -Warning: Attempt to modify property 'p' of non-object in %sbug44660.php on line 21 +Attempt to modify property 'p' of non-object --> Confirm assignments have had no impact: bool(true) diff --git a/Zend/tests/bug44899.phpt b/Zend/tests/bug44899.phpt index d62033a24e..d9c0de0ef7 100644 --- a/Zend/tests/bug44899.phpt +++ b/Zend/tests/bug44899.phpt @@ -34,5 +34,5 @@ echo "\n"; isset empty -Notice: Undefined property: myclass::$foo in %s on line %d +Warning: Undefined property: myclass::$foo in %s on line %d empty diff --git a/Zend/tests/bug45186.phpt b/Zend/tests/bug45186.phpt index 411c2ea072..1c25a86921 100644 --- a/Zend/tests/bug45186.phpt +++ b/Zend/tests/bug45186.phpt @@ -31,10 +31,14 @@ $x->test(); call_user_func(array('BAR','x')); call_user_func('BAR::www'); -call_user_func('self::y'); +try { + call_user_func('self::y'); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- +--EXPECT-- __call: string(3) "ABC" __call: @@ -50,5 +54,4 @@ string(1) "y" ok __callstatic: string(3) "www" - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active in %sbug45186.php on line 31 +call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active diff --git a/Zend/tests/bug45186_2.phpt b/Zend/tests/bug45186_2.phpt index 7c813a909c..cb098136a0 100644 --- a/Zend/tests/bug45186_2.phpt +++ b/Zend/tests/bug45186_2.phpt @@ -26,11 +26,19 @@ $x = new bar; $x->test(); call_user_func(array('BAR','x')); -call_user_func('BAR::www'); -call_user_func('self::y'); +try { + call_user_func('BAR::www'); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func('self::y'); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- +--EXPECT-- __call: string(3) "ABC" __call: @@ -44,7 +52,5 @@ string(1) "y" __call: string(1) "y" ok - -Warning: call_user_func() expects parameter 1 to be a valid callback, class 'bar' does not have a method 'www' in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active in %sbug45186_2.php on line 27 +call_user_func() expects parameter 1 to be a valid callback, class 'bar' does not have a method 'www' +call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active diff --git a/Zend/tests/bug45805.phpt b/Zend/tests/bug45805.phpt index d63e658868..86cea70373 100644 --- a/Zend/tests/bug45805.phpt +++ b/Zend/tests/bug45805.phpt @@ -38,7 +38,7 @@ $o->bar(); --EXPECTF-- Fatal error: Uncaught RuntimeException in %sbug45805.php:%d Stack trace: -#0 %sbug45805.php(%d): PHPUnit_Util_ErrorHandler::handleError(8, 'Only variables ...', '%s', %d, Array) +#0 %sbug45805.php(%d): PHPUnit_Util_ErrorHandler::handleError(8, 'Only variables ...', '%s', %d) #1 [internal function]: B->foo() #2 %sbug45805.php(%d): ReflectionMethod->invoke(Object(B)) #3 %sbug45805.php(%d): B->bar() diff --git a/Zend/tests/bug46106.phpt b/Zend/tests/bug46106.phpt index f18c25a6c2..b0e769e05a 100644 --- a/Zend/tests/bug46106.phpt +++ b/Zend/tests/bug46106.phpt @@ -15,8 +15,13 @@ function test($x) { } $x = new ReflectionFunction('str_pad'); -test($x); +try { + test($x); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> DONE --EXPECT-- +str_pad() expects at least 2 parameters, 1 given DONE diff --git a/Zend/tests/bug46196.phpt b/Zend/tests/bug46196.phpt index 7a6a753d87..9b2ca618ee 100644 --- a/Zend/tests/bug46196.phpt +++ b/Zend/tests/bug46196.phpt @@ -22,10 +22,8 @@ function myErrorHandler($errno, $errstr, $errfile, $errline) } ?> -===DONE=== --EXPECT-- *** Testing restore_error_handler() : error bug #46196 *** NULL bool(true) NULL -===DONE=== diff --git a/Zend/tests/bug46304.phpt b/Zend/tests/bug46304.phpt index 9898838907..f8b9a0b525 100644 --- a/Zend/tests/bug46304.phpt +++ b/Zend/tests/bug46304.phpt @@ -6,9 +6,6 @@ Bug #46304 (defining namespaced constant using define()) define('NS1\ns2\const1','value1'); define('ns1\ns2\const2','value2'); define('ns1\NS2\coNSt3','value3'); -define('NS1\ns2\const4','value4', true); -define('ns1\ns2\const5','value5', true); -define('ns1\NS2\coNSt6','value6', true); print NS1\ns2\const1 . "\n"; print ns1\ns2\const1 . "\n"; @@ -22,29 +19,9 @@ print NS1\ns2\coNSt3 . "\n"; print ns1\ns2\coNSt3 . "\n"; print ns1\ns2\coNSt3 . "\n"; -print NS1\ns2\const4 . "\n"; -print ns1\ns2\const4 . "\n"; -print ns1\NS2\const4 . "\n"; -print ns1\ns2\coNSt4 . "\n"; - -print NS1\ns2\const5 . "\n"; -print ns1\ns2\const5 . "\n"; -print ns1\NS2\const5 . "\n"; -print ns1\ns2\coNSt5 . "\n"; - -print NS1\ns2\const6 . "\n"; -print ns1\ns2\const6 . "\n"; -print ns1\NS2\const6 . "\n"; -print ns1\ns2\coNSt6 . "\n"; - print NS1\ns2\coNSt1 . "\n"; ?> --EXPECTF-- -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 6 - -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 7 - -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 8 value1 value1 value1 @@ -54,28 +31,6 @@ value2 value3 value3 value3 -value4 -value4 -value4 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS1\ns2\const4" in %s on line 25 -value4 -value5 -value5 -value5 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\ns2\const5" in %s on line 30 -value5 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 32 -value6 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 33 -value6 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 34 -value6 -value6 Fatal error: Uncaught Error: Undefined constant 'NS1\ns2\coNSt1' in %sbug46304.php:%d Stack trace: diff --git a/Zend/tests/bug47054.phpt b/Zend/tests/bug47054.phpt index 9e89c2c208..f607365bdc 100644 --- a/Zend/tests/bug47054.phpt +++ b/Zend/tests/bug47054.phpt @@ -24,8 +24,6 @@ $c->s(); get_called_class(); -D::m(); - ?> --EXPECTF-- Called class: D @@ -33,11 +31,3 @@ Called class: C Called class: C Warning: get_called_class() called from outside a class in %s on line %d - -Deprecated: Non-static method D::m() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d -Stack trace: -#0 %s(%d): D::m() -#1 {main} - thrown in %s on line %d diff --git a/Zend/tests/bug47109.phpt b/Zend/tests/bug47109.phpt index 0b86a2bcd3..4f8f4b9328 100644 --- a/Zend/tests/bug47109.phpt +++ b/Zend/tests/bug47109.phpt @@ -5,6 +5,6 @@ Bug #47109 (Memory leak on $a->{"a"."b"} when $a is not an object) $a->{"a"."b"}; ?> --EXPECTF-- -Notice: Undefined variable: a in %sbug47109.php on line 2 +Warning: Undefined variable: a in %s on line %d -Notice: Trying to get property 'ab' of non-object in %sbug47109.php on line 2 +Warning: Trying to get property 'ab' of non-object in %s on line %d diff --git a/Zend/tests/bug47320.phpt b/Zend/tests/bug47320.phpt deleted file mode 100644 index 47db35edac..0000000000 --- a/Zend/tests/bug47320.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Bug #47320 ($php_errormsg out of scope in functions) ---INI-- -display_errors=0 -track_errors=1 ---FILE-- -<?php -if (!@substr('no 2nd parameter')) { - echo '$php_errormsg in global: ' . $php_errormsg . "\n"; -} - -function foo() { - if (!@strpos('no 2nd parameter')) { - echo '$php_errormsg in function: ' . $php_errormsg . "\n"; - - echo '$GLOBALS[php_errormsg] in function: ' . - $GLOBALS['php_errormsg'] . "\n"; - } -} - -foo(); -?> ---EXPECT-- -$php_errormsg in global: substr() expects at least 2 parameters, 1 given -$php_errormsg in function: strpos() expects at least 2 parameters, 1 given -$GLOBALS[php_errormsg] in function: substr() expects at least 2 parameters, 1 given diff --git a/Zend/tests/bug47572.phpt b/Zend/tests/bug47572.phpt index 67bb3ec111..7a44cc6e7f 100644 --- a/Zend/tests/bug47572.phpt +++ b/Zend/tests/bug47572.phpt @@ -14,4 +14,7 @@ $foo = new Foo(); ?> --EXPECTF-- -Warning: Use of undefined constant FOO - assumed 'FOO' (this will throw an Error in a future version of PHP) in %s on line %d +Fatal error: Uncaught Error: Undefined constant 'FOO' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug47836.phpt b/Zend/tests/bug47836.phpt index 5a93a44c71..15afc68c48 100644 --- a/Zend/tests/bug47836.phpt +++ b/Zend/tests/bug47836.phpt @@ -4,12 +4,16 @@ Bug #47836 (array operator [] inconsistency when the array has PHP_INT_MAX index <?php $arr[PHP_INT_MAX] = 1; -$arr[] = 2; +try { + $arr[] = 2; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($arr); ?> --EXPECTF-- -Warning: Cannot add element to the array as the next element is already occupied in %s on line 4 +Cannot add element to the array as the next element is already occupied array(1) { [%d]=> int(1) diff --git a/Zend/tests/bug47981.phpt b/Zend/tests/bug47981.phpt deleted file mode 100644 index fba320bb13..0000000000 --- a/Zend/tests/bug47981.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Bug #47981 (error handler not called regardless) ---INI-- -error_reporting=0 ---FILE-- -<?php -function errh($errno, $errstr) { - var_dump($errstr); -} -set_error_handler("errh"); - -interface a{} -class b implements a { function f($a=1) {}} -class c extends b {function f() {}} -?> ---EXPECT-- -string(60) "Declaration of c::f() should be compatible with b::f($a = 1)" diff --git a/Zend/tests/bug48004.phpt b/Zend/tests/bug48004.phpt deleted file mode 100644 index 5968876520..0000000000 --- a/Zend/tests/bug48004.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Bug #48004 (Error handler prevents creation of default object) ---FILE-- -<?php -function error_handler($errno, $errstr, $errfile, $errline, $errcontext) { - return true; -} - -function test() { - $data->id = 1; - print_r($data); -} - -set_error_handler("error_handler"); -test(); -?> ---EXPECT-- -stdClass Object -( - [id] => 1 -) diff --git a/Zend/tests/bug48215.phpt b/Zend/tests/bug48215.phpt index 4582057d98..6af1867361 100644 --- a/Zend/tests/bug48215.phpt +++ b/Zend/tests/bug48215.phpt @@ -27,10 +27,8 @@ class B extends A $b = new B(); $b->A(); ?> -===DONE=== --EXPECT-- B::__construct A::__construct B::A A::A -===DONE=== diff --git a/Zend/tests/bug48533.phpt b/Zend/tests/bug48533.phpt index 4fa49a2f22..3dfbc658ec 100644 --- a/Zend/tests/bug48533.phpt +++ b/Zend/tests/bug48533.phpt @@ -26,8 +26,8 @@ $x->a(); $x->b(); $x->c(); $x::a(); -$x::b(); $x::c(); +$x::b(); ?> --EXPECTF-- @@ -35,7 +35,9 @@ string(9) "__call::a" int(2) string(9) "__call::c" string(15) "__callStatic::a" - -Deprecated: Non-static method foo::b() should not be called statically in %s on line %d -int(2) string(15) "__callStatic::c" + +Fatal error: Uncaught Error: Non-static method foo::b() cannot be called statically in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug48693.phpt b/Zend/tests/bug48693.phpt deleted file mode 100644 index f916b6407b..0000000000 --- a/Zend/tests/bug48693.phpt +++ /dev/null @@ -1,52 +0,0 @@ ---TEST-- -Bug #48693 (Double declaration of __lambda_func when lambda wrongly formatted) ---FILE-- -<?php - -try { - $x = create_function('', 'return 1; }'); -} catch (ParseError $e) { - echo "$e\n\n"; -} -try { - $y = create_function('', 'function a() { }; return 2;'); -} catch (ParseError $e) { - echo "$e\n\n"; -} -try { - $z = create_function('', '{'); -} catch (ParseError $e) { - echo "$e\n\n"; -} -try { - $w = create_function('', 'return 3;'); -} catch (ParseError $e) { - echo "$e\n\n"; -} - -var_dump( - $y(), - $w() -); - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -ParseError: syntax error, unexpected '}', expecting end of file in %sbug48693.php(4) : runtime-created function:1 -Stack trace: -#0 %sbug48693.php(4): create_function('', 'return 1; }') -#1 {main} - - -Deprecated: Function create_function() is deprecated in %s on line %d - -Deprecated: Function create_function() is deprecated in %s on line %d -ParseError: syntax error, unexpected end of file in %sbug48693.php(14) : runtime-created function:1 -Stack trace: -#0 %sbug48693.php(14): create_function('', '{') -#1 {main} - - -Deprecated: Function create_function() is deprecated in %s on line %d -int(2) -int(3) diff --git a/Zend/tests/bug49908.phpt b/Zend/tests/bug49908.phpt index e3e91d3452..8ab6307180 100644 --- a/Zend/tests/bug49908.phpt +++ b/Zend/tests/bug49908.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #49908 (throwing exception in __autoload crashes when interface is not defined) +Bug #49908 (throwing exception in autoloader crashes when interface is not defined) --FILE-- <?php diff --git a/Zend/tests/bug50261.phpt b/Zend/tests/bug50261.phpt deleted file mode 100644 index 321e9cfb8b..0000000000 --- a/Zend/tests/bug50261.phpt +++ /dev/null @@ -1,39 +0,0 @@ ---TEST-- -Bug #50261 (Crash When Calling Parent Constructor with call_user_func()) ---FILE-- -<?php - -class testClass { - function testClass($x) { - echo __METHOD__, " (". $x . ")\n"; - } -} - -class testClass2 extends testClass { - function __construct() { - static $x = 0; - - if ($x) { - print "Infinite loop...\n"; - } else { - $x++; - - parent::__construct(1); - testclass::__construct(2); - call_user_func(array('parent', '__construct'), 3); - call_user_func(array('testclass', '__construct'), 4); - call_user_func(array('testclass', 'testclass'), 5); - } - } -} - -new testClass2; - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; testClass has a deprecated constructor in %s on line %d -testClass::testClass (1) -testClass::testClass (2) -testClass::testClass (3) -testClass::testClass (4) -testClass::testClass (5) diff --git a/Zend/tests/bug51394.phpt b/Zend/tests/bug51394.phpt index e2d260b2b2..e31bc230cd 100644 --- a/Zend/tests/bug51394.phpt +++ b/Zend/tests/bug51394.phpt @@ -15,6 +15,6 @@ $a = $empty($b); --EXPECTF-- Fatal error: Uncaught Exception: error! in %sbug51394.php:%d Stack trace: -#0 %sbug51394.php(%d): eh(8, 'Undefined varia%s', '%s', %d, Array) +#0 %s(%d): eh(2, 'Undefined varia...', '%s', %d) #1 {main} thrown in %sbug51394.php on line %d diff --git a/Zend/tests/bug51827.phpt b/Zend/tests/bug51827.phpt index 0834749454..77bdc069c3 100644 --- a/Zend/tests/bug51827.phpt +++ b/Zend/tests/bug51827.phpt @@ -16,4 +16,8 @@ register_shutdown_function('exploDe'); --EXPECTF-- int(1) -Warning: explode() expects at least 2 parameters, 0 given in Unknown on line %d +Fatal error: Uncaught ArgumentCountError: explode() expects at least 2 parameters, 0 given in [no active file]:0 +Stack trace: +#0 [internal function]: explode() +#1 {main} + thrown in [no active file] on line 0 diff --git a/Zend/tests/bug52001.phpt b/Zend/tests/bug52001.phpt index cf55d195b9..36170eb96b 100644 --- a/Zend/tests/bug52001.phpt +++ b/Zend/tests/bug52001.phpt @@ -11,7 +11,7 @@ var_dump($temp1); function a($b,$c) {} ?> --EXPECTF-- -Notice: Undefined variable: var in %sbug52001.php on line 2 +Warning: Undefined variable: var in %s on line %d -Notice: Undefined variable: in %sbug52001.php on line 2 +Warning: Undefined variable: in %s on line %d int(1) diff --git a/Zend/tests/bug52041.phpt b/Zend/tests/bug52041.phpt index a1eb1f841b..467a29fe77 100644 --- a/Zend/tests/bug52041.phpt +++ b/Zend/tests/bug52041.phpt @@ -6,12 +6,36 @@ function foo() { return $x; } -foo()->a = 1; -foo()->a->b = 2; -foo()->a++; -foo()->a->b++; -foo()->a += 2; -foo()->a->b += 2; +try { + foo()->a = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + foo()->a->b = 2; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + foo()->a++; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + foo()->a->b++; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + foo()->a += 2; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + foo()->a->b += 2; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} foo()[0] = 1; foo()[0][0] = 2; @@ -23,71 +47,47 @@ foo()[0][0] += 2; var_dump(foo()); ?> --EXPECTF-- -Notice: Undefined variable: x in %sbug52041.php on line 3 - -Warning: Creating default object from empty value in %sbug52041.php on line 6 - -Notice: Undefined variable: x in %sbug52041.php on line 3 - -Warning: Creating default object from empty value in %sbug52041.php on line 7 - -Warning: Creating default object from empty value in %sbug52041.php on line 7 - -Notice: Undefined variable: x in %sbug52041.php on line 3 - -Warning: Creating default object from empty value in %sbug52041.php on line 8 - -Notice: Undefined property: stdClass::$a in %sbug52041.php on line 8 - -Notice: Undefined variable: x in %sbug52041.php on line 3 - -Warning: Creating default object from empty value in %sbug52041.php on line 9 - -Notice: Undefined property: stdClass::$a in %sbug52041.php on line 9 - -Warning: Creating default object from empty value in %sbug52041.php on line 9 - -Notice: Undefined property: stdClass::$b in %sbug52041.php on line 9 - -Notice: Undefined variable: x in %sbug52041.php on line 3 - -Warning: Creating default object from empty value in %sbug52041.php on line 10 - -Notice: Undefined property: stdClass::$a in %sbug52041.php on line 10 +Warning: Undefined variable: x in %s on line %d +Attempt to assign property 'a' of non-object -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d +Attempt to modify property 'a' of non-object -Warning: Creating default object from empty value in %sbug52041.php on line 11 +Warning: Undefined variable: x in %s on line %d +Attempt to increment/decrement property 'a' of non-object -Notice: Undefined property: stdClass::$a in %sbug52041.php on line 11 +Warning: Undefined variable: x in %s on line %d +Attempt to modify property 'a' of non-object -Warning: Creating default object from empty value in %sbug52041.php on line 11 +Warning: Undefined variable: x in %s on line %d +Attempt to assign property 'a' of non-object -Notice: Undefined property: stdClass::$b in %sbug52041.php on line 11 +Warning: Undefined variable: x in %s on line %d +Attempt to modify property 'a' of non-object -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d -Notice: Undefined offset: 0 in %sbug52041.php on line 15 +Notice: Undefined offset: 0 in %s on line %d -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d -Notice: Undefined offset: 0 in %sbug52041.php on line 16 +Notice: Undefined offset: 0 in %s on line %d -Notice: Undefined offset: 0 in %sbug52041.php on line 16 +Notice: Undefined offset: 0 in %s on line %d -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d -Notice: Undefined offset: 0 in %sbug52041.php on line 17 +Notice: Undefined offset: 0 in %s on line %d -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d -Notice: Undefined offset: 0 in %sbug52041.php on line 18 +Notice: Undefined offset: 0 in %s on line %d -Notice: Undefined offset: 0 in %sbug52041.php on line 18 +Notice: Undefined offset: 0 in %s on line %d -Notice: Undefined variable: x in %sbug52041.php on line 3 +Warning: Undefined variable: x in %s on line %d NULL diff --git a/Zend/tests/bug52051.phpt b/Zend/tests/bug52051.phpt deleted file mode 100644 index acfddbc36d..0000000000 --- a/Zend/tests/bug52051.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -Bug #52051 (handling of case sensitivity of old-style constructors changed in 5.3+) ---FILE-- -<?php - -class AA { - function AA() { echo "foo\n"; } -} -class bb extends AA {} -class CC extends bb { - function CC() { parent::bb(); } -} -new CC(); - -class A { - function A() { echo "bar\n"; } -} -class B extends A {} -class C extends B { - function C() { parent::B(); } -} -new C(); - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; AA has a deprecated constructor in %s on line %d - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; CC has a deprecated constructor in %s on line %d - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; A has a deprecated constructor in %s on line %d - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; C has a deprecated constructor in %s on line %d -foo -bar diff --git a/Zend/tests/bug52160.phpt b/Zend/tests/bug52160.phpt deleted file mode 100644 index f0a57000e0..0000000000 --- a/Zend/tests/bug52160.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -Bug #52160 (Invalid E_DEPRECATED redefined constructor error) ---FILE-- -<?php - -class bar { - function __construct() { } - static function bar() { - var_dump(1); - } -} - -bar::bar(); - -class foo { - static function foo() { - var_dump(2); - } - function __construct() { } -} - -foo::foo(); - -class baz { - static function baz() { - var_dump(3); - } -} - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; baz has a deprecated constructor in %s on line %d - -Fatal error: Constructor baz::baz() cannot be static in %s on line %d diff --git a/Zend/tests/bug52237.phpt b/Zend/tests/bug52237.phpt deleted file mode 100644 index 44f8f3f688..0000000000 --- a/Zend/tests/bug52237.phpt +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -Bug #52237 (Crash when passing the reference of the property of a non-object) ---FILE-- -<?php -$data = 'test'; -preg_match('//', '', $data->info); -var_dump($data); -?> ---EXPECTF-- -Warning: Attempt to modify property 'info' of non-object in %sbug52237.php on line 3 -string(4) "test" diff --git a/Zend/tests/bug52614.phpt b/Zend/tests/bug52614.phpt index 0a1dca6882..77a5f30f67 100644 --- a/Zend/tests/bug52614.phpt +++ b/Zend/tests/bug52614.phpt @@ -52,7 +52,11 @@ var_dump($foo->a2); $foo->f3()[0] = 1; var_dump($foo->a3); -$foo->f4()->a = 1; +try { + $foo->f4()->a = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($foo->o1); $foo->f5()->a = 1; @@ -65,16 +69,15 @@ $foo->f1()[0]++; var_dump($foo->a1[0]); $foo->f6()[0]++; var_dump($foo->a1[0]); ---EXPECTF-- +--EXPECT-- NULL array(0) { } array(0) { } - -Warning: Creating default object from empty value in %sbug52614.php on line 52 +Attempt to assign property 'a' of non-object NULL -object(stdClass)#%d (1) { +object(stdClass)#3 (1) { ["a"]=> int(1) } diff --git a/Zend/tests/bug54262.phpt b/Zend/tests/bug54262.phpt deleted file mode 100644 index 16933ca300..0000000000 --- a/Zend/tests/bug54262.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Bug #54262 (Crash when assigning value to a dimension in a non-array) ---FILE-- -<?php -$a = '0'; -var_dump(isset($a['b'])); -$simpleString = preg_match('//', '', $a->a); -$simpleString["wrong"] = "f"; -echo "ok\n"; -?> ---EXPECTF-- -bool(false) - -Warning: Attempt to modify property 'a' of non-object in %sbug54262.php on line 4 - -Warning: Cannot use a scalar value as an array in %sbug54262.php on line 5 -ok diff --git a/Zend/tests/bug54265.phpt b/Zend/tests/bug54265.phpt deleted file mode 100644 index 417e1b5564..0000000000 --- a/Zend/tests/bug54265.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Bug #54265 (crash when variable gets reassigned in error handler) ---FILE-- -<?php -function my_errorhandler($errno,$errormsg) { - global $my_var; - $my_var = 0; - echo "EROOR: $errormsg\n"; -} -set_error_handler("my_errorhandler"); -$my_var = str_repeat("A",$my_var[0]->errormsg = "xyz"); -echo "ok\n"; -?> ---EXPECT-- -EROOR: Creating default object from empty value -ok diff --git a/Zend/tests/bug54585.phpt b/Zend/tests/bug54585.phpt deleted file mode 100644 index deabe55af8..0000000000 --- a/Zend/tests/bug54585.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Bug #54585 (track_errors causes segfault) ---INI-- -track_errors=On ---FILE-- -<?php -function testing($source) { - unset($source[$cos]); -} -testing($_GET); -echo "ok\n"; -?> ---EXPECTF-- -Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0 - -Notice: Undefined variable: cos in %sbug54585.php on line 3 -ok diff --git a/Zend/tests/bug60536_001.phpt b/Zend/tests/bug60536_001.phpt index 0847b81d40..b4630f4b87 100644 --- a/Zend/tests/bug60536_001.phpt +++ b/Zend/tests/bug60536_001.phpt @@ -22,5 +22,5 @@ $a->__construct(); echo "DONE"; ?> --EXPECTF-- -Notice: Undefined property: Z::$x in %s on line 14 +Warning: Undefined property: Z::$x in %s on line %d DONE diff --git a/Zend/tests/bug60573.phpt b/Zend/tests/bug60573.phpt index 871be56a16..50650f5419 100644 --- a/Zend/tests/bug60573.phpt +++ b/Zend/tests/bug60573.phpt @@ -53,32 +53,6 @@ public function setSelf(self $s) { } } -class Foo5 extends Base { - -public function setSelf(parent $s) { } - -} - -class Bar5 extends Foo5 { - -public function setSelf(parent $s) { } - -} - -abstract class Foo6 extends Base { - -abstract public function setSelf(parent $s); - -} - -class Bar6 extends Foo6 { - -public function setSelf(Foo6 $s) { } - -} +?> --EXPECTF-- -Warning: Declaration of Bar4::setSelf(Bar4 $s) should be compatible with Foo4::setSelf(Foo4 $s) in %sbug60573.php on line %d - -Warning: Declaration of Bar5::setSelf(Foo5 $s) should be compatible with Foo5::setSelf(Base $s) in %sbug60573.php on line %d - -Fatal error: Declaration of Bar6::setSelf(Foo6 $s) must be compatible with Foo6::setSelf(Base $s) in %sbug60573.php on line %d +Fatal error: Declaration of Bar4::setSelf(Bar4 $s) must be compatible with Foo4::setSelf(Foo4 $s) in %s on line %d diff --git a/Zend/tests/bug60573_2.phpt b/Zend/tests/bug60573_2.phpt new file mode 100644 index 0000000000..221745316a --- /dev/null +++ b/Zend/tests/bug60573_2.phpt @@ -0,0 +1,64 @@ +--TEST-- +Bug #60573 (type hinting with "self" keyword causes weird errors) -- variation 2 +--FILE-- +<?php +class Foo1 { + +public function setSelf(self $s) { } + +} + +class Bar1 extends Foo1 { + +public function setSelf(parent $s) { } + +} + +class Foo2 { + +public function setSelf(Foo2 $s) { } + +} + +class Bar2 extends Foo2 { + +public function setSelf(parent $s) { } + +} + +class Base { +} + +class Foo3 extends Base{ + +public function setSelf(parent $s) { } + +} + +class Bar3 extends Foo3 { + +public function setSelf(Base $s) { } + +} + +class Foo4 { + +public function setSelf(self $s) { } + +} + +class Foo5 extends Base { + +public function setSelf(parent $s) { } + +} + +class Bar5 extends Foo5 { + +public function setSelf(parent $s) { } + +} + +?> +--EXPECTF-- +Fatal error: Declaration of Bar5::setSelf(Foo5 $s) must be compatible with Foo5::setSelf(Base $s) in %sbug60573_2.php on line %d diff --git a/Zend/tests/bug60909_1.phpt b/Zend/tests/bug60909_1.phpt index e4c07face1..d674490302 100644 --- a/Zend/tests/bug60909_1.phpt +++ b/Zend/tests/bug60909_1.phpt @@ -13,7 +13,7 @@ require 'notfound.php'; error(require(notfound.php): failed to open stream: %s) Warning: Uncaught Exception: Foo in %sbug60909_1.php:5 Stack trace: -#0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8, Array) +#0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8) #1 %sbug60909_1.php(8): require() #2 {main} thrown in %sbug60909_1.php on line 5 diff --git a/Zend/tests/bug60978.phpt b/Zend/tests/bug60978.phpt index 676808c7a3..5dc6fe31e7 100644 --- a/Zend/tests/bug60978.phpt +++ b/Zend/tests/bug60978.phpt @@ -1,11 +1,5 @@ --TEST-- Bug #60978 (exit code incorrect) ---SKIPIF-- -<?php - if ("cli" != php_sapi_name()) { - echo "skip CLI only"; - } -?> --FILE-- <?php $php = getenv('TEST_PHP_EXECUTABLE'); diff --git a/Zend/tests/bug61011.phpt b/Zend/tests/bug61011.phpt index dc0aca64f8..b9088c68f1 100644 --- a/Zend/tests/bug61011.phpt +++ b/Zend/tests/bug61011.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #61011 (Crash when an exception is thrown by __autoload accessing a static property) +Bug #61011 (Crash when an exception is thrown by autoloader accessing a static property) --FILE-- <?php spl_autoload_register(function ($name) { diff --git a/Zend/tests/bug61095.phpt b/Zend/tests/bug61095.phpt index 4ca196cd15..ce5426ca65 100644 --- a/Zend/tests/bug61095.phpt +++ b/Zend/tests/bug61095.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #61095 (Lexing 0x00*+<NUM> incorectly) +Bug #61095 (Lexing 0x00*+<NUM> incorrectly) --FILE-- <?php echo 0x00+2; diff --git a/Zend/tests/bug61225.phpt b/Zend/tests/bug61225.phpt index 33d74bd561..6baa00ace2 100644 --- a/Zend/tests/bug61225.phpt +++ b/Zend/tests/bug61225.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #61225 (Lexing 0b0*+<NUM> incorectly) +Bug #61225 (Lexing 0b0*+<NUM> incorrectly) --FILE-- <?php echo 0b00+1; diff --git a/Zend/tests/bug61767.phpt b/Zend/tests/bug61767.phpt index 5e949706e8..3bc1e49d09 100644 --- a/Zend/tests/bug61767.phpt +++ b/Zend/tests/bug61767.phpt @@ -19,7 +19,7 @@ Error handler called (Undefined variable: undefined) Fatal error: Uncaught ErrorException: Undefined variable: undefined in %sbug61767.php:%d Stack trace: -#0 %sbug61767.php(%d): {closure}(%s, 'Undefined varia...', '%s', %d, Array) +#0 %sbug61767.php(%d): {closure}(%s, 'Undefined varia...', '%s', %d) #1 {main} thrown in %sbug61767.php on line %d Shutting down diff --git a/Zend/tests/bug62005.phpt b/Zend/tests/bug62005.phpt deleted file mode 100644 index 83158d5cc2..0000000000 --- a/Zend/tests/bug62005.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Bug #62005 (unexpected behavior when incrementally assigning to a member of a null object) ---FILE-- -<?php -function add_points($player, $points) { - $player->energy += $points; - print_r($player); -} -add_points(NULL, 2); ---EXPECTF-- -Warning: Creating default object from empty value in %sbug62005.php on line %d - -Notice: Undefined property: stdClass::$energy in %sbug62005.php on line 3 -stdClass Object -( - [energy] => 2 -) diff --git a/Zend/tests/bug63336.phpt b/Zend/tests/bug63336.phpt deleted file mode 100644 index 271d3e82a9..0000000000 --- a/Zend/tests/bug63336.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Bug #63336 (invalid E_NOTICE error occur) ---FILE-- -<?php -error_reporting(E_ALL & ~E_WARNING); -define("TEST", "123"); -class Base { - const DUMMY = "XXX"; - public function foo($var=TEST, $more=null) { return true; } - public function bar($more=self::DUMMY) { return true; } -} - -class Child extends Base { - const DUMMY = "DDD"; - public function foo($var=TEST, array $more = array()) { return true; } - public function bar($var, $more=self::DUMMY) { return true; } -} -?> ---EXPECTF-- -Warning: Declaration of Child::foo($var = TEST, array $more = Array) should be compatible with Base::foo($var = TEST, $more = NULL) in %sbug63336.php on line %d - -Warning: Declaration of Child::bar($var, $more = self::DUMMY) should be compatible with Base::bar($more = self::DUMMY) in %sbug63336.php on line %d diff --git a/Zend/tests/bug63462.phpt b/Zend/tests/bug63462.phpt index 45c9507bba..bcc2c67997 100644 --- a/Zend/tests/bug63462.phpt +++ b/Zend/tests/bug63462.phpt @@ -52,16 +52,16 @@ $test->privateProperty = 'value'; --EXPECTF-- __get nonExisting -Notice: Undefined property: Test::$nonExisting in %s on line %d +Warning: Undefined property: Test::$nonExisting in %s on line %d __get publicProperty -Notice: Undefined property: Test::$publicProperty in %s on line %d +Warning: Undefined property: Test::$publicProperty in %s on line %d __get protectedProperty -Notice: Undefined property: Test::$protectedProperty in %s on line %d +Warning: Undefined property: Test::$protectedProperty in %s on line %d __get privateProperty -Notice: Undefined property: Test::$privateProperty in %s on line %d +Warning: Undefined property: Test::$privateProperty in %s on line %d __isset nonExisting __isset publicProperty __isset protectedProperty diff --git a/Zend/tests/bug64960.phpt b/Zend/tests/bug64960.phpt index 52af0bbe32..4ee4042617 100644 --- a/Zend/tests/bug64960.phpt +++ b/Zend/tests/bug64960.phpt @@ -33,7 +33,7 @@ Notice: ob_end_flush(): failed to delete and flush buffer. No buffer to delete o Fatal error: Uncaught Exception in %sbug64960.php:19 Stack trace: -#0 [internal function]: {closure}(8, 'ob_end_clean():...', '%s', 9, Array) +#0 [internal function]: {closure}(8, 'ob_end_clean():...', '%s', 9) #1 %sbug64960.php(9): ob_end_clean() #2 [internal function]: ExceptionHandler->__invoke(Object(Exception)) #3 {main} diff --git a/Zend/tests/bug64988.phpt b/Zend/tests/bug64988.phpt index 41d89cc54c..7e2289f5b2 100644 --- a/Zend/tests/bug64988.phpt +++ b/Zend/tests/bug64988.phpt @@ -26,5 +26,4 @@ $o = new Smooth1(); echo "okey"; ?> --EXPECTF-- -Warning: Declaration of Smooth1::insert(array $data) should be compatible with Noisy1::insert(array $data, $option1 = NULL) in %sbug64988.php on line 17 -okey +Fatal error: Declaration of Smooth1::insert(array $data) must be compatible with Noisy1::insert(array $data, $option1 = NULL) in %sbug64988.php on line 17 diff --git a/Zend/tests/bug65322.phpt b/Zend/tests/bug65322.phpt index 4985ae55d6..2ae2780bb6 100644 --- a/Zend/tests/bug65322.phpt +++ b/Zend/tests/bug65322.phpt @@ -15,10 +15,10 @@ set_error_handler(function($_, $msg, $file) { /* This is just a particular example of a non-fatal compile-time error * If this breaks in future, just find another example and use it instead */ -eval('class A { function test() { } } class B extends A { function test($a) { } }'); +eval('class A { private function __invoke() { } }'); ?> --EXPECTF-- -string(62) "Declaration of B::test($a) should be compatible with A::test()" +string(76) "The magic method __invoke() must have public visibility and cannot be static" string(%d) "%s(%d) : eval()'d code" string(1) "X" diff --git a/Zend/tests/bug66015.phpt b/Zend/tests/bug66015.phpt index 5e0815240d..1222ab3a96 100644 --- a/Zend/tests/bug66015.phpt +++ b/Zend/tests/bug66015.phpt @@ -24,7 +24,6 @@ class Test $test = new Test(); ?> -===DONE=== --EXPECT-- array ( 1 => 'first', @@ -32,4 +31,3 @@ array ( 3 => 'third', 4 => 4, ) -===DONE=== diff --git a/Zend/tests/bug66218.phpt b/Zend/tests/bug66218.phpt index d800605ac8..db3c7c655a 100644 --- a/Zend/tests/bug66218.phpt +++ b/Zend/tests/bug66218.phpt @@ -2,7 +2,6 @@ Bug #66218 zend_register_functions breaks reflection --SKIPIF-- <?php -if (PHP_SAPI != "cli") die("skip CLI only test"); if (!function_exists("dl")) die("skip need dl"); ?> --FILE-- diff --git a/Zend/tests/bug66609.phpt b/Zend/tests/bug66609.phpt index 206f7757d9..880f5a58a4 100644 --- a/Zend/tests/bug66609.phpt +++ b/Zend/tests/bug66609.phpt @@ -24,5 +24,5 @@ $foo->blah--; //crash echo "okey"; ?> --EXPECTF-- -Notice: Undefined property: Bar::$bar in %sbug66609.php on line %d +Warning: Undefined property: Bar::$bar in %s on line %d okey diff --git a/Zend/tests/bug67314.phpt b/Zend/tests/bug67314.phpt index c5b6a1293d..3ef225de03 100644 --- a/Zend/tests/bug67314.phpt +++ b/Zend/tests/bug67314.phpt @@ -15,8 +15,8 @@ echo "made it once\n"; crash(); echo "ok\n"; --EXPECTF-- -Notice: Undefined variable: i in %sbug67314.php on line 4 +Warning: Undefined variable: i in %s on line %d made it once -Notice: Undefined variable: i in %sbug67314.php on line 4 +Warning: Undefined variable: i in %s on line %d ok diff --git a/Zend/tests/bug67436/b.inc b/Zend/tests/bug67436/b.inc index 793a1394d6..bb2521f61f 100644 --- a/Zend/tests/bug67436/b.inc +++ b/Zend/tests/bug67436/b.inc @@ -1,7 +1,9 @@ <?php class b extends a { - public function test() { + private function __invoke() {} + + public function test($arg = c::TESTCONSTANT) { echo __METHOD__ . "()\n"; parent::test(); } diff --git a/Zend/tests/bug67436/bug67436.phpt b/Zend/tests/bug67436/bug67436.phpt index 0ef339dc47..14db266831 100644 --- a/Zend/tests/bug67436/bug67436.phpt +++ b/Zend/tests/bug67436/bug67436.phpt @@ -2,6 +2,8 @@ bug67436: Autoloader isn't called if user defined error handler is present --INI-- error_reporting=-1 +--SKIPIF-- +<?php if (extension_loaded('Zend OPCache')) die('skip Opcache overrides error handler'); ?> --FILE-- <?php @@ -12,6 +14,7 @@ spl_autoload_register(function($classname) { }); set_error_handler(function ($errno, $errstr, $errfile, $errline) { + var_dump($errstr); }, error_reporting()); a::staticTest(); @@ -19,5 +22,6 @@ a::staticTest(); $b = new b(); $b->test(); --EXPECT-- +string(76) "The magic method __invoke() must have public visibility and cannot be static" b::test() a::test(c::TESTCONSTANT) diff --git a/Zend/tests/bug67436/bug67436_nohandler.phpt b/Zend/tests/bug67436/bug67436_nohandler.phpt index a155ccc842..5394177064 100644 --- a/Zend/tests/bug67436/bug67436_nohandler.phpt +++ b/Zend/tests/bug67436/bug67436_nohandler.phpt @@ -14,6 +14,6 @@ a::staticTest(); $b = new b(); $b->test(); --EXPECTF-- -Warning: Declaration of b::test() should be compatible with a::test($arg = c::TESTCONSTANT) in %s%ebug67436%eb.inc on line %d +Warning: The magic method __invoke() must have public visibility and cannot be static in %s on line %d b::test() a::test(c::TESTCONSTANT) diff --git a/Zend/tests/bug67858.phpt b/Zend/tests/bug67858.phpt deleted file mode 100644 index 1186cd6a6f..0000000000 --- a/Zend/tests/bug67858.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Bug #67858: Leak when $php_errormsg already set ---INI-- -track_errors=1 -error_reporting=E_ALL ---FILE-- -<?php - -function f() { - $php_errormsg = [1, 2, 3]; - echo $var; - var_dump($php_errormsg); -} -f(); - -?> ---EXPECTF-- -Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0 - -Notice: Undefined variable: var in %s on line %d -string(23) "Undefined variable: var" diff --git a/Zend/tests/bug67938.phpt b/Zend/tests/bug67938.phpt index 6597c4895f..fc8a9ab517 100644 --- a/Zend/tests/bug67938.phpt +++ b/Zend/tests/bug67938.phpt @@ -20,8 +20,10 @@ class Test implements TestInterface { $obj = new Test; $obj->foo(); $obj->bar([]); +$obj->bar([], 1); ?> --EXPECT-- Test::foo Test::bar +Test::bar diff --git a/Zend/tests/bug68446.phpt b/Zend/tests/bug68446.phpt index 9648966691..91685ebb5e 100644 --- a/Zend/tests/bug68446.phpt +++ b/Zend/tests/bug68446.phpt @@ -9,7 +9,7 @@ function a(array $a = FOO) { var_dump($a); } -function b(array $b = BAR) { +function b(?array $b = BAR) { var_dump($b); } diff --git a/Zend/tests/bug68797.phpt b/Zend/tests/bug68797.phpt index db0306049f..0202a63125 100644 --- a/Zend/tests/bug68797.phpt +++ b/Zend/tests/bug68797.phpt @@ -7,7 +7,5 @@ precision=17 echo 2.2250738585072012e-308, "\n"; ?> -==DONE== --EXPECT-- 2.2250738585072014E-308 -==DONE== diff --git a/Zend/tests/bug69017.phpt b/Zend/tests/bug69017.phpt index 762fcbc9a0..d6d20d7c08 100644 --- a/Zend/tests/bug69017.phpt +++ b/Zend/tests/bug69017.phpt @@ -16,14 +16,18 @@ class c1 c1::$a1[] = 1; c1::$a2[] = 1; -c1::$a3[] = 1; +try { + c1::$a3[] = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump(c1::$a1); var_dump(c1::$a2); var_dump(c1::$a3); ?> --EXPECTF-- -Warning: Cannot add element to the array as the next element is already occupied in %sbug69017.php on line %d +Cannot add element to the array as the next element is already occupied array(2) { [1]=> string(3) "one" diff --git a/Zend/tests/bug69388.phpt b/Zend/tests/bug69388.phpt index bf0c0a3c39..3846cca4ca 100644 --- a/Zend/tests/bug69388.phpt +++ b/Zend/tests/bug69388.phpt @@ -3,7 +3,7 @@ Bug #69388: Use after free on recursive calls to PHP compiler --FILE-- <?php -function handle_error($code, $message, $file, $line, $context) { +function handle_error($code, $message, $file, $line) { if (!function_exists("bla")) { eval('function bla($s) {echo "$s\n";}'); } diff --git a/Zend/tests/bug69388_2.phpt b/Zend/tests/bug69388_2.phpt index b55153b492..40b14e0257 100644 --- a/Zend/tests/bug69388_2.phpt +++ b/Zend/tests/bug69388_2.phpt @@ -2,7 +2,7 @@ Bug #69388 - Variation --FILE-- <?php -function handle_error($code, $message, $file, $line, $context) { +function handle_error($code, $message, $file, $line) { eval('namespace Foo;'); echo "$message\n"; } diff --git a/Zend/tests/bug69732.phpt b/Zend/tests/bug69732.phpt index f5571627fe..578cb8d143 100644 --- a/Zend/tests/bug69732.phpt +++ b/Zend/tests/bug69732.phpt @@ -20,7 +20,7 @@ $wpq->interesting =& ret_assoc(); $x = $wpq->interesting; printf("%s\n", $x); --EXPECTF-- -Notice: Undefined property: wpq::$interesting in %sbug69732.php on line 6 +Warning: Undefined property: wpq::$interesting in %s on line %d Notice: Indirect modification of overloaded property wpq::$interesting has no effect in %sbug69732.php on line 16 diff --git a/Zend/tests/bug69755.phpt b/Zend/tests/bug69755.phpt index 08432808e2..e419756d26 100644 --- a/Zend/tests/bug69755.phpt +++ b/Zend/tests/bug69755.phpt @@ -5,4 +5,7 @@ Bug #69755: segfault in ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER c . 10; ?> --EXPECTF-- -Warning: Use of undefined constant c - assumed 'c' (this will throw an Error in a future version of PHP) in %sbug69755.php on line 2 +Fatal error: Uncaught Error: Undefined constant 'c' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug69767.phpt b/Zend/tests/bug69767.phpt index 9458546dea..095bfd89d5 100644 --- a/Zend/tests/bug69767.phpt +++ b/Zend/tests/bug69767.phpt @@ -5,4 +5,4 @@ Bug #69767 (Default parameter value with wrong type segfaults) function foo(String $bar = 0) {} ?> --EXPECTF-- -Fatal error: Default value for parameters with a string type can only be string or NULL in %sbug69767.php on line %d +Fatal error: Cannot use int as default value for parameter $bar of type string in %s on line %d diff --git a/Zend/tests/bug69788.phpt b/Zend/tests/bug69788.phpt index ff028411b1..e847b3b0a5 100644 --- a/Zend/tests/bug69788.phpt +++ b/Zend/tests/bug69788.phpt @@ -3,6 +3,7 @@ Bug #69788: Malformed script causes Uncaught Error in php-cgi, valgrind SIGILL --FILE-- <?php [t.[]]; ?> --EXPECTF-- -Warning: Use of undefined constant t - assumed 't' (this will throw an Error in a future version of PHP) in %s on line %d - -Notice: Array to string conversion in %s on line %d +Fatal error: Uncaught Error: Undefined constant 't' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug70124.phpt b/Zend/tests/bug70124.phpt index f32a8613fe..87ec4ab41d 100644 --- a/Zend/tests/bug70124.phpt +++ b/Zend/tests/bug70124.phpt @@ -39,7 +39,7 @@ try { } ?> --EXPECTF-- -Notice: Undefined variable: f in %sbug70124.php on line %d +Warning: Undefined variable: f in %s on line %d string(30) "Function name must be a string" string(31) "Call to undefined method A::y()" string(31) "Call to undefined method A::y()" diff --git a/Zend/tests/bug70681.phpt b/Zend/tests/bug70681.phpt index 9dd09b07b8..d0cc9523a9 100644 --- a/Zend/tests/bug70681.phpt +++ b/Zend/tests/bug70681.phpt @@ -12,5 +12,5 @@ var_dump($c("foo")); ?> --EXPECTF-- -Warning: Cannot unbind $this of internal method in %s on line %d +Warning: Cannot unbind $this of method in %s on line %d int(3) diff --git a/Zend/tests/bug70895.phpt b/Zend/tests/bug70895.phpt index 896bf00a7b..71ff19a0b5 100644 --- a/Zend/tests/bug70895.phpt +++ b/Zend/tests/bug70895.phpt @@ -3,13 +3,23 @@ Bug #70895 null ptr deref and segfault with crafted callable --FILE-- <?php -array_map("%n", 0); -array_map("%n %i", 0); -array_map("%n %i aoeu %f aoeu %p", 0); +try { + array_map("%n", 0); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + array_map("%n %i", 0); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + array_map("%n %i aoeu %f aoeu %p", 0); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTREGEX-- -Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n' not found or invalid function name in .+ - -Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n %i' not found or invalid function name in .+ - -Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n %i aoeu %f aoeu %p' not found or invalid function name in .+bug70895.php on line \d+ +--EXPECT-- +array_map() expects parameter 1 to be a valid callback, function '%n' not found or invalid function name +array_map() expects parameter 1 to be a valid callback, function '%n %i' not found or invalid function name +array_map() expects parameter 1 to be a valid callback, function '%n %i aoeu %f aoeu %p' not found or invalid function name diff --git a/Zend/tests/bug70898.phpt b/Zend/tests/bug70898.phpt index e31ee894bf..fa6e96d83f 100644 --- a/Zend/tests/bug70898.phpt +++ b/Zend/tests/bug70898.phpt @@ -2,21 +2,15 @@ Bug #70895 null ptr deref and segfault with crafted callable --FILE-- <?php - function m($f,$a){ - return array_map($f,0); - } +function m($f,$a){ + return array_map($f,0); +} - echo implode(m("",m("",m("",m("",m("0000000000000000000000000000000000",(""))))))); +try { + echo implode(m("",m("",m("",m("",m("0000000000000000000000000000000000",(""))))))); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- -Warning: array_map() expects parameter 1 to be a valid callback, function '0000000000000000000000000000000000' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: implode(): Argument must be an array in %sbug70898.php on line %d +--EXPECT-- +array_map() expects parameter 1 to be a valid callback, function '0000000000000000000000000000000000' not found or invalid function name diff --git a/Zend/tests/bug70957.phpt b/Zend/tests/bug70957.phpt index 7db7d7d023..ad2115e4a0 100644 --- a/Zend/tests/bug70957.phpt +++ b/Zend/tests/bug70957.phpt @@ -19,4 +19,4 @@ class B extends Foo } ?> --EXPECTF-- -Warning: Declaration of T::bar() should be compatible with Foo::bar($a = 'Foo') in %sbug70957.php on line %d +Fatal error: Declaration of T::bar() must be compatible with Foo::bar($a = 'Foo') in %sbug70957.php on line %d diff --git a/Zend/tests/bug71221.phpt b/Zend/tests/bug71221.phpt index 0f6ee16946..b55a14a2bd 100644 --- a/Zend/tests/bug71221.phpt +++ b/Zend/tests/bug71221.phpt @@ -2,9 +2,10 @@ Bug #71221 (Null pointer deref (segfault) in get_defined_vars via ob_start) --FILE-- <?php -ob_start("get_defined_vars"); -ob_end_clean(); -?> -okey +register_shutdown_function("get_defined_vars"); --EXPECT-- -okey +Fatal error: Uncaught Error: Cannot call get_defined_vars() dynamically in [no active file]:0 +Stack trace: +#0 [internal function]: get_defined_vars() +#1 {main} + thrown in [no active file] on line 0 diff --git a/Zend/tests/bug71300.phpt b/Zend/tests/bug71300.phpt index 3589c4764e..fc4b23681a 100644 --- a/Zend/tests/bug71300.phpt +++ b/Zend/tests/bug71300.phpt @@ -24,5 +24,5 @@ var_dump(test2()); --EXPECTF-- string(4) "test" -Notice: Array to string conversion in %sbug71300.php on line %d +Warning: Array to string conversion in %s on line %d string(9) "Arraytest" diff --git a/Zend/tests/bug71428.1.phpt b/Zend/tests/bug71428.1.phpt index 490fc30070..acecd85fc5 100644 --- a/Zend/tests/bug71428.1.phpt +++ b/Zend/tests/bug71428.1.phpt @@ -9,4 +9,4 @@ class B extends A { public function m(array $a = []) {} } --EXPECTF-- -Warning: Declaration of B::m(array $a = Array) should be compatible with A::m(?array $a = NULL) in %sbug71428.1.php on line 6 +Fatal error: Declaration of B::m(array $a = Array) must be compatible with A::m(?array $a = NULL) in %sbug71428.1.php on line 6 diff --git a/Zend/tests/bug71428.2.phpt b/Zend/tests/bug71428.2.phpt index 9fc15fc8c5..0056bd8144 100644 --- a/Zend/tests/bug71428.2.phpt +++ b/Zend/tests/bug71428.2.phpt @@ -5,13 +5,13 @@ bug #71428.2: inheritance of ye olde dynamic interfaces --FILE-- <?php interface StatementInterface { - public function fetch($first = null, $second, $third); + public function fetch(int $first = PDO::FETCH_BOTH, int $second = PDO::FETCH_ORI_NEXT, int $third = 0); } class Statement extends PDOStatement implements StatementInterface {} interface StatementInterface1 { - public function fetch($first = null, $second = null, $third = null); + public function fetch(int $first = PDO::FETCH_ASSOC, int $second = PDO::FETCH_ORI_PRIOR, int $third = 1); } class Statement1 extends PDOStatement implements StatementInterface1 {} diff --git a/Zend/tests/bug71428.3.phpt b/Zend/tests/bug71428.3.phpt index 78fff6e70d..ab3cc9ae16 100644 --- a/Zend/tests/bug71428.3.phpt +++ b/Zend/tests/bug71428.3.phpt @@ -7,4 +7,4 @@ class B { public function m(A $a = NULL, $n) { echo "B.m";} }; class C extends B { public function m(A $a , $n) { echo "C.m";} }; ?> --EXPECTF-- -Warning: Declaration of C::m(A $a, $n) should be compatible with B::m(?A $a, $n) in %sbug71428.3.php on line 4 +Fatal error: Declaration of C::m(A $a, $n) must be compatible with B::m(?A $a, $n) in %sbug71428.3.php on line 4 diff --git a/Zend/tests/bug71539_5.phpt b/Zend/tests/bug71539_5.phpt index 7e89971ec2..bd08de5eb6 100644 --- a/Zend/tests/bug71539_5.phpt +++ b/Zend/tests/bug71539_5.phpt @@ -3,18 +3,17 @@ Bug #71539.5 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes) --FILE-- <?php $array = []; -$array['']->prop =& $array[0]; +$array[''][0] =& $array[0]; $array[0] = 42; var_dump($array); ?> ---EXPECTF-- -Warning: Creating default object from empty value in %sbug71539_5.php on line 3 +--EXPECT-- array(2) { [0]=> &int(42) [""]=> - object(stdClass)#1 (1) { - ["prop"]=> + array(1) { + [0]=> &int(42) } } diff --git a/Zend/tests/bug71572.phpt b/Zend/tests/bug71572.phpt index f4f44449cd..063a98fcb9 100644 --- a/Zend/tests/bug71572.phpt +++ b/Zend/tests/bug71572.phpt @@ -10,7 +10,6 @@ var_dump($str[3] = ""); var_dump($str[10] = ""); var_dump($str); ?> -==DONE== --EXPECTF-- Warning: Cannot assign an empty string to a string offset in %s on line %d NULL @@ -24,4 +23,3 @@ NULL Warning: Cannot assign an empty string to a string offset in %s on line %d NULL string(3) "abc" -==DONE== diff --git a/Zend/tests/bug71841.phpt b/Zend/tests/bug71841.phpt index f66761b3c9..35b805a2a7 100644 --- a/Zend/tests/bug71841.phpt +++ b/Zend/tests/bug71841.phpt @@ -1,23 +1,33 @@ --TEST-- Bug #71841 (EG(error_zval) is not handled well) ---INI-- -error_reporting=0 --FILE-- <?php $z = unserialize('O:1:"A":0:{}'); -var_dump($z->e.=0); -var_dump(++$z->x); -var_dump($z->y++); +@var_dump($z->e.=0); +@var_dump(++$z->x); +@var_dump($z->y++); $y = array(PHP_INT_MAX => 0); -var_dump($y[] .= 0); -var_dump(++$y[]); -var_dump($y[]++); +try { + var_dump($y[] .= 0); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(++$y[]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump($y[]++); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECT-- NULL NULL NULL -NULL -NULL -NULL +Cannot add element to the array as the next element is already occupied +Cannot add element to the array as the next element is already occupied +Cannot add element to the array as the next element is already occupied diff --git a/Zend/tests/bug72057.phpt b/Zend/tests/bug72057.phpt index 406efe3efc..a518d82948 100644 --- a/Zend/tests/bug72057.phpt +++ b/Zend/tests/bug72057.phpt @@ -13,7 +13,7 @@ set_error_handler( --EXPECTF-- Fatal error: Uncaught Exception: My custom error in %s:%d Stack trace: -#0 %s(%d): {closure}(8, 'A non well form...', '%s', %d, Array) +#0 %s(%d): {closure}(8, 'A non well form...', '%s', %d) #1 %s(%d): {closure}('7as') #2 {main} thrown in %s on line %d diff --git a/Zend/tests/bug72101.phpt b/Zend/tests/bug72101.phpt index 808627be3b..23861958fd 100644 --- a/Zend/tests/bug72101.phpt +++ b/Zend/tests/bug72101.phpt @@ -76,7 +76,7 @@ $foo->bar($a, $b, $c); --EXPECTF-- Fatal error: Uncaught Error: Class 'DoesNotExists' not found in %sbug72101.php:61 Stack trace: -#0 %sbug72101.php(8): {closure}(2, 'Parameter 1 to ...', '%s', 8, Array) +#0 %sbug72101.php(8): {closure}(2, 'Parameter 1 to ...', '%s', 8) #1 %sbug72101.php(27): PHPUnit_Framework_MockObject_Stub_ReturnCallback->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) #2 %sbug72101.php(19): PHPUnit_Framework_MockObject_Matcher->invoked(Object(PHPUnit_Framework_MockObject_Invocation_Static)) #3 %sbug72101.php(52): PHPUnit_Framework_MockObject_InvocationMocker->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) diff --git a/Zend/tests/bug72107.phpt b/Zend/tests/bug72107.phpt index 3f4c46cf70..c22f657ebb 100644 --- a/Zend/tests/bug72107.phpt +++ b/Zend/tests/bug72107.phpt @@ -6,9 +6,11 @@ set_error_handler('func_get_args'); function test($a) { echo $undef; } -test(1); +try { + test(1); +} catch (\Error $e) { + echo $e->getMessage(); +} ?> ---EXPECTF-- -Warning: Cannot call func_get_args() dynamically in %s on line %d - -Notice: Undefined variable: undef in %s on line %d +--EXPECT-- +Cannot call func_get_args() dynamically diff --git a/Zend/tests/bug72911.phpt b/Zend/tests/bug72911.phpt deleted file mode 100644 index 0d290caca7..0000000000 --- a/Zend/tests/bug72911.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Bug #72911 (Memleak in zend_binary_assign_op_obj_helper) ---FILE-- -<?php - -$a = 0; - -$b = $a->b->i -= 0; - -var_dump($b); - -?> ---EXPECTF-- -Warning: Attempt to modify property 'b' of non-object in %sbug72911.php on line %d -NULL diff --git a/Zend/tests/bug72918.phpt b/Zend/tests/bug72918.phpt index 403d4e69c5..92ee518de5 100644 --- a/Zend/tests/bug72918.phpt +++ b/Zend/tests/bug72918.phpt @@ -13,10 +13,8 @@ $string[-3] EOT; ?> -===DONE=== --EXPECT-- foo c foo c -===DONE=== diff --git a/Zend/tests/bug72944.phpt b/Zend/tests/bug72944.phpt index 0ee8bd62c6..0ddc99ff3b 100644 --- a/Zend/tests/bug72944.phpt +++ b/Zend/tests/bug72944.phpt @@ -2,11 +2,10 @@ Bug #72944 (Null pointer deref in zval_delref_p). --FILE-- <?php +define('e', 'e'); ("a"== e & $A = $A? 0 : 0) ?:0; echo "OK\n"; ?> --EXPECTF-- -Warning: Use of undefined constant e - assumed 'e' (this will throw an Error in a future version of PHP) in %sbug72944.php on line 2 - -Notice: Undefined variable: A in %sbug72944.php on line 2 +Warning: Undefined variable: A in %s on line %d OK diff --git a/Zend/tests/bug73163.phpt b/Zend/tests/bug73163.phpt deleted file mode 100644 index 5c0560458d..0000000000 --- a/Zend/tests/bug73163.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Bug #73163 (PHP hangs if error handler throws while accessing undef const in default value) ---FILE-- -<?php - -function doSomething(string $value = UNDEFINED) { -} - -set_error_handler(function($errno, $errstr) { - throw new Exception($errstr); -}); - -doSomething(); - -?> ---EXPECTF-- -Fatal error: Uncaught Exception: Use of undefined constant UNDEFINED - assumed 'UNDEFINED' (this will throw an Error in a future version of PHP) in %s:%d -Stack trace: -#0 %s(%d): {closure}(%s) -#1 %s(%d): doSomething() -#2 {main} - thrown in %s on line %d diff --git a/Zend/tests/bug73181.phpt b/Zend/tests/bug73181.phpt deleted file mode 100644 index 3ab93ebf5b..0000000000 --- a/Zend/tests/bug73181.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Bug #73181: parse_str() without a second argument leads to crash ---FILE-- -<?php - -function x() { - parse_str("1&x"); - var_dump(get_defined_vars()); -} - -x(); - -?> ---EXPECTF-- -Deprecated: parse_str(): Calling parse_str() without the result argument is deprecated in %s on line %d -array(2) { - [1]=> - string(0) "" - ["x"]=> - string(0) "" -} diff --git a/Zend/tests/bug73338.phpt b/Zend/tests/bug73338.phpt index df4c3b66e4..816a526445 100644 --- a/Zend/tests/bug73338.phpt +++ b/Zend/tests/bug73338.phpt @@ -14,5 +14,6 @@ try { (function() { call_user_func("fail"); })(); } catch (Error $e) {} try { [new class { static function foo() {} function __destruct () { throw new Error; } }, "foo"](); } catch (Error $e) {} ?> ---EXPECTF-- -Warning: call_user_func() expects parameter 1 to be a valid callback, no array or string given in %s on line %d +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/bug74084.phpt b/Zend/tests/bug74084.phpt index 2e65471bcc..ab4dce0a5a 100644 --- a/Zend/tests/bug74084.phpt +++ b/Zend/tests/bug74084.phpt @@ -4,16 +4,34 @@ Bug #74084 (Out of bound read - zend_mm_alloc_small) error_reporting=0 --FILE-- <?php -$$A += $$B->a = &$$C; +$$A += $$B['a'] = &$$C; unset($$A); -$$A -= $$B->a = &$$C; +try { + $$A -= $$B['a'] = &$$C; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} unset($$A); -$$A *= $$B->a = &$$C; +try { + $$A *= $$B['a'] = &$$C; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} unset($$A); -$$A /= $$B->a = &$$C; +try { + $$A /= $$B['a'] = &$$C; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} unset($$A); -$$A **= $$B->a = &$$C; -var_dump($$A); +try { + $$A **= $$B['a'] = &$$C; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECT-- -int(1) +Unsupported operand types +Unsupported operand types +Unsupported operand types +Unsupported operand types diff --git a/Zend/tests/bug74340.phpt b/Zend/tests/bug74340.phpt index f266dcc236..64d1b91b14 100644 --- a/Zend/tests/bug74340.phpt +++ b/Zend/tests/bug74340.phpt @@ -24,7 +24,7 @@ $test->test; --EXPECTF-- __get test -Notice: Undefined property: Test::$test in %s on line %d +Warning: Undefined property: Test::$test in %s on line %d __get test2 -Notice: Undefined property: Test::$test in %s on line %d +Warning: Undefined property: Test::$test in %s on line %d diff --git a/Zend/tests/bug74408.phpt b/Zend/tests/bug74408.phpt deleted file mode 100644 index e770a51dc8..0000000000 --- a/Zend/tests/bug74408.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -Bug #74408 (Endless loop bypassing execution time limit) ---FILE-- -<?php - - class ErrorHandling { - - public function error_handler($errno, $errstr, $errfile, $errline) { - $bla = new NonExistingClass2(); - } - - public function exception_handler(Error $e) { - echo "Caught, exception: " . $e->getMessage(); - } - } - - set_error_handler('ErrorHandling::error_handler'); - set_exception_handler('ErrorHandling::exception_handler'); - - $blubb = new NonExistingClass(); -?> ---EXPECTF-- -Deprecated: Non-static method ErrorHandling::error_handler() should not be called statically in %sbug74408.php on line %d - -Deprecated: Non-static method ErrorHandling::error_handler() should not be called statically in %sbug74408.php on line %d - -Deprecated: Non-static method ErrorHandling::error_handler() should not be called statically in Unknown on line 0 - -Fatal error: Uncaught Error: Class 'NonExistingClass2' not found in %sbug74408.php:%d -Stack trace: -#0 [internal function]: ErrorHandling::error_handler(8192, 'Non-static meth...', '%s', %d, Array) -#1 %sbug74408.php(%d): set_exception_handler('ErrorHandling::...') -#2 {main} - thrown in %sbug74408.php on line %d diff --git a/Zend/tests/bug75241.phpt b/Zend/tests/bug75241.phpt index 1751bbee76..d6c2d79e2d 100644 --- a/Zend/tests/bug75241.phpt +++ b/Zend/tests/bug75241.phpt @@ -2,12 +2,12 @@ Bug #75241 (Null pointer dereference in zend_mm_alloc_small()) --FILE-- <?php -function eh(){} - -set_error_handler('eh'); $d->d = &$d + $d->d/=0; var_dump($d); ?> ---EXPECT-- -float(INF) +--EXPECTF-- +Fatal error: Uncaught Error: Attempt to modify property 'd' of non-object in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug75573.phpt b/Zend/tests/bug75573.phpt index f5e87f8283..867f5d597f 100644 --- a/Zend/tests/bug75573.phpt +++ b/Zend/tests/bug75573.phpt @@ -6,6 +6,10 @@ Bug #75573 (Segmentation fault in 7.1.12 and 7.0.26) class A { var $_stdObject; + function __construct() + { + $this->_stdObject = new stdClass; + } function &__get($property) { if (isset($this->_stdObject->{$property})) { @@ -44,9 +48,7 @@ var_dump($b->name); var_dump($b->settings); ?> --EXPECTF-- -Warning: Creating default object from empty value in %sbug75573.php on line %d - -Notice: Only variable references should be returned by reference in %sbug75573.php on line %d +Notice: Only variable references should be returned by reference in %s on line %d string(3) "abc" array(2) { ["foo"]=> diff --git a/Zend/tests/bug75921.phpt b/Zend/tests/bug75921.phpt index 917dd413cc..a8649262b5 100644 --- a/Zend/tests/bug75921.phpt +++ b/Zend/tests/bug75921.phpt @@ -3,78 +3,65 @@ Bug #75921: Inconsistent error when creating stdObject from empty variable --FILE-- <?php -$null->a = 42; +try { + $null->a = 42; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($null); unset($null); -$null->a['hello'] = 42; +try { + $null->a['hello'] = 42; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($null); unset($null); -$null->a->b = 42; +try { + $null->a->b = 42; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($null); unset($null); -$null->a['hello']->b = 42; +try { + $null->a['hello']->b = 42; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($null); unset($null); -$null->a->b['hello'] = 42; +try { + $null->a->b['hello'] = 42; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($null); unset($null); ?> --EXPECTF-- -Warning: Creating default object from empty value in %sbug75921.php on line 3 -object(stdClass)#1 (1) { - ["a"]=> - int(42) -} +Attempt to assign property 'a' of non-object -Warning: Creating default object from empty value in %sbug75921.php on line 7 -object(stdClass)#1 (1) { - ["a"]=> - array(1) { - ["hello"]=> - int(42) - } -} - -Warning: Creating default object from empty value in %sbug75921.php on line 11 - -Warning: Creating default object from empty value in %sbug75921.php on line 11 -object(stdClass)#1 (1) { - ["a"]=> - object(stdClass)#2 (1) { - ["b"]=> - int(42) - } -} +Warning: Undefined variable: null in %s on line %d +NULL +Attempt to modify property 'a' of non-object -Warning: Creating default object from empty value in %sbug75921.php on line 15 +Warning: Undefined variable: null in %s on line %d +NULL +Attempt to modify property 'a' of non-object -Warning: Creating default object from empty value in %sbug75921.php on line 15 -object(stdClass)#1 (1) { - ["a"]=> - array(1) { - ["hello"]=> - object(stdClass)#2 (1) { - ["b"]=> - int(42) - } - } -} +Warning: Undefined variable: null in %s on line %d +NULL +Attempt to modify property 'a' of non-object -Warning: Creating default object from empty value in %sbug75921.php on line 19 +Warning: Undefined variable: null in %s on line %d +NULL +Attempt to modify property 'a' of non-object -Warning: Creating default object from empty value in %sbug75921.php on line 19 -object(stdClass)#1 (1) { - ["a"]=> - object(stdClass)#2 (1) { - ["b"]=> - array(1) { - ["hello"]=> - int(42) - } - } -} +Warning: Undefined variable: null in %s on line %d +NULL diff --git a/Zend/tests/bug76025.phpt b/Zend/tests/bug76025.phpt index 2619984d1e..903cec2607 100644 --- a/Zend/tests/bug76025.phpt +++ b/Zend/tests/bug76025.phpt @@ -13,6 +13,6 @@ $c = $b[$a]; --EXPECTF-- Fatal error: Uncaught Exception: blah in %sbug76025.php:%d Stack trace: -#0 %sbug76025.php(%d): handleError(8, 'Undefined varia...', '%s', %d, Array) +#0 %s(%d): handleError(2, 'Undefined varia...', '%s', %d) #1 {main} thrown in %sbug76025.php on line %d diff --git a/Zend/tests/bug76534.phpt b/Zend/tests/bug76534.phpt index 956a29ba2c..457d09f400 100644 --- a/Zend/tests/bug76534.phpt +++ b/Zend/tests/bug76534.phpt @@ -12,6 +12,6 @@ $y = &$x["bar"]; --EXPECTF-- Fatal error: Uncaught Exception: Illegal string offset 'bar' in %sbug76534.php:%d Stack trace: -#0 %sbug76534.php(%d): {closure}(2, 'Illegal string ...', '%s', %d, Array) +#0 %sbug76534.php(%d): {closure}(2, 'Illegal string ...', '%s', %d) #1 {main} thrown in %sbug76534.php on line %d diff --git a/Zend/tests/bug76667.phpt b/Zend/tests/bug76667.phpt index 15dc34693d..09f17b56c7 100644 --- a/Zend/tests/bug76667.phpt +++ b/Zend/tests/bug76667.phpt @@ -19,20 +19,20 @@ $x = new T; $x->x = 1; ?> --EXPECTF-- -Notice: Undefined variable: undefined in %sbug76667.php on line %d +Warning: Undefined variable: undefined in %s on line %d -Notice: Trying to get property '1' of non-object in %sbug76667.php on line %d +Warning: Trying to get property '1' of non-object in %s on line %d Warning: Division by zero in %sbug76667.php on line %d -Notice: Undefined variable: undefined in %sbug76667.php on line %d +Warning: Undefined variable: undefined in %s on line %d -Notice: Trying to get property 'NAN' of non-object in %sbug76667.php on line %d +Warning: Trying to get property 'NAN' of non-object in %s on line %d Warning: Division by zero in %sbug76667.php on line %d -Notice: Undefined variable: undefined in %sbug76667.php on line %d +Warning: Undefined variable: undefined in %s on line %d -Notice: Trying to get property 'NAN' of non-object in %sbug76667.php on line %d +Warning: Trying to get property 'NAN' of non-object in %s on line %d Warning: Division by zero in %sbug76667.php on line %d diff --git a/Zend/tests/bug76860.phpt b/Zend/tests/bug76860.phpt index 046edba7f2..67baa3996f 100644 --- a/Zend/tests/bug76860.phpt +++ b/Zend/tests/bug76860.phpt @@ -17,15 +17,15 @@ new B; --EXPECTF-- Notice: Accessing static property B::$a as non static in %sbug76860.php on line 7 -Notice: Undefined property: B::$a in %sbug76860.php on line 7 +Warning: Undefined property: B::$a in %s on line %d Notice: Accessing static property B::$b as non static in %sbug76860.php on line 7 -Notice: Undefined property: B::$b in %sbug76860.php on line 7 +Warning: Undefined property: B::$b in %s on line %d Notice: Accessing static property B::$c as non static in %sbug76860.php on line 7 -Notice: Undefined property: B::$c in %sbug76860.php on line 7 +Warning: Undefined property: B::$c in %s on line %d NULL NULL NULL diff --git a/Zend/tests/bug76860_2.phpt b/Zend/tests/bug76860_2.phpt index bc92702fc1..1ab85f69f2 100644 --- a/Zend/tests/bug76860_2.phpt +++ b/Zend/tests/bug76860_2.phpt @@ -20,15 +20,15 @@ new B; --EXPECTF-- Notice: Accessing static property B::$a as non static in %sbug76860_2.php on line 7 -Notice: Undefined property: B::$a in %sbug76860_2.php on line 7 +Warning: Undefined property: B::$a in %s on line %d Notice: Accessing static property B::$b as non static in %sbug76860_2.php on line 7 -Notice: Undefined property: B::$b in %sbug76860_2.php on line 7 +Warning: Undefined property: B::$b in %s on line %d Notice: Accessing static property B::$c as non static in %sbug76860_2.php on line 7 -Notice: Undefined property: B::$c in %sbug76860_2.php on line 7 +Warning: Undefined property: B::$c in %s on line %d NULL NULL NULL diff --git a/Zend/tests/bug76965.phpt b/Zend/tests/bug76965.phpt index 1a8e7d2d35..ce157733a5 100644 --- a/Zend/tests/bug76965.phpt +++ b/Zend/tests/bug76965.phpt @@ -15,7 +15,6 @@ END; var_dump(parse_ini_string($ini, false, INI_SCANNER_RAW)); ?> -===DONE=== --EXPECT-- array(7) { [1]=> @@ -33,4 +32,3 @@ array(7) { [7]=> string(7) "foo"bar" } -===DONE=== diff --git a/Zend/tests/bug77291.phpt b/Zend/tests/bug77291.phpt index 2960648a7c..e5977eba08 100644 --- a/Zend/tests/bug77291.phpt +++ b/Zend/tests/bug77291.phpt @@ -35,8 +35,6 @@ var_dump(isset($foo->a)); $foo = new Foo45; var_dump($foo->a); ?> -===DONE=== --EXPECT-- bool(true) string(10) "Some value" -===DONE=== diff --git a/Zend/tests/bug77494.phpt b/Zend/tests/bug77494.phpt index 1793f6b219..adab05bef7 100644 --- a/Zend/tests/bug77494.phpt +++ b/Zend/tests/bug77494.phpt @@ -12,5 +12,5 @@ var_dump($a->name); --EXPECTF-- Warning: CURLFile() has been disabled for security reasons in %sbug77494.php on line 2 -Notice: Undefined property: CURLFile::$name in %sbug77494.php on line 3 +Warning: Undefined property: CURLFile::$name in %s on line %d NULL diff --git a/Zend/tests/bug77738.phpt b/Zend/tests/bug77738.phpt index e3a453c405..c664a31344 100644 --- a/Zend/tests/bug77738.phpt +++ b/Zend/tests/bug77738.phpt @@ -5,4 +5,7 @@ Bug #77738 (Nullptr deref in zend_compile_expr) __COMPILER_HALT_OFFSET__; ; // <- important --EXPECTF-- -Warning: Use of undefined constant __COMPILER_HALT_OFFSET__ - assumed '__COMPILER_HALT_OFFSET__' %sbug77738.php on line %d +Fatal error: Uncaught Error: Undefined constant '__COMPILER_HALT_OFFSET__' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug78182.phpt b/Zend/tests/bug78182.phpt index 4b0f08dc3b..d7f10e94df 100644 --- a/Zend/tests/bug78182.phpt +++ b/Zend/tests/bug78182.phpt @@ -4,12 +4,13 @@ Bug #78182: Segmentation fault during by-reference property assignment <?php $varName = 'var'; $propName = 'prop'; -$$varName->$propName =& $$varName; +try { + $$varName->$propName =& $$varName; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($var); ?> ---EXPECTF-- -Warning: Creating default object from empty value in %s on line %d -object(stdClass)#1 (1) { - ["prop"]=> - *RECURSION* -} +--EXPECT-- +Attempt to modify property 'prop' of non-object +NULL diff --git a/Zend/tests/bug78239.phpt b/Zend/tests/bug78239.phpt index 94908a785b..aa81af4452 100644 --- a/Zend/tests/bug78239.phpt +++ b/Zend/tests/bug78239.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #78239: Deprecation notice during string conversion converted to exception hangs +--SKIPIF-- +<?php if (!extension_loaded("zend-test")) die("skip requires zend-test extension"); ?> --FILE-- <?php function handleError($level, $message, $file = '', $line = 0, $context = []) @@ -9,21 +11,12 @@ function handleError($level, $message, $file = '', $line = 0, $context = []) set_error_handler('handleError'); -class A -{ - - public function abc(): bool - { - return false; - } -} - -$r = new ReflectionMethod("A", "abc"); -(string)$r->getReturnType() ?: ""; +$r = new _ZendTestClass; +(string)$r ?: ""; ?> --EXPECTF-- -Fatal error: Uncaught ErrorException: Function ReflectionType::__toString() is deprecated in %s:%d +Fatal error: Uncaught ErrorException: Function _ZendTestClass::__toString() is deprecated in %s:%d Stack trace: #0 %s(%d): handleError(%s) #1 {main} diff --git a/Zend/tests/bug78531.phpt b/Zend/tests/bug78531.phpt index ba460ee05a..1e8f0b34d1 100644 --- a/Zend/tests/bug78531.phpt +++ b/Zend/tests/bug78531.phpt @@ -2,17 +2,36 @@ Bug #78531 (Crash when using undefined variable as object) --FILE-- <?php -@$u1->a += 5; -var_dump($u1->a); -@$x = ++$u2->a; -var_dump($u2->a); -@$x = $u3->a++; -var_dump($u3->a); -@$u4->a->a += 5; -var_dump($u4->a->a); +try { + $u1->a += 5; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + $x = ++$u2->a; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + $x = $u3->a++; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + $u4->a->a += 5; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECT-- -int(5) -int(1) -int(1) -int(5)
\ No newline at end of file +--EXPECTF-- +Warning: Undefined variable: u1 in %s on line %d +Attempt to assign property 'a' of non-object + +Warning: Undefined variable: u2 in %s on line %d +Attempt to increment/decrement property 'a' of non-object + +Warning: Undefined variable: u3 in %s on line %d +Attempt to increment/decrement property 'a' of non-object + +Warning: Undefined variable: u4 in %s on line %d +Attempt to modify property 'a' of non-object diff --git a/Zend/tests/bug_debug_backtrace.phpt b/Zend/tests/bug_debug_backtrace.phpt index 71ce129201..95530e01e4 100644 --- a/Zend/tests/bug_debug_backtrace.phpt +++ b/Zend/tests/bug_debug_backtrace.phpt @@ -18,11 +18,9 @@ eval("foo();"); echo "Done\n"; ?> -===DONE=== --EXPECTF-- #0 boo() called at [%s:%d] #1 bar() called at [%s:%d] #2 foo() called at [%s(%d) : eval()'d code:1] #3 eval() called at [%s:%d] Done -===DONE=== diff --git a/Zend/tests/call_static_006.phpt b/Zend/tests/call_static_006.phpt index 2887afa355..946be2a3c9 100644 --- a/Zend/tests/call_static_006.phpt +++ b/Zend/tests/call_static_006.phpt @@ -4,29 +4,15 @@ Testing __callStatic <?php class foo { - public function aa() { - print "ok\n"; - } static function __callstatic($a, $b) { var_dump($a); } } -foo::aa(); - -$b = 'AA'; -foo::$b(); - foo::__construct(); ?> --EXPECTF-- -Deprecated: Non-static method foo::aa() should not be called statically in %s on line %d -ok - -Deprecated: Non-static method foo::aa() should not be called statically in %s on line %d -ok - Fatal error: Uncaught Error: Cannot call constructor in %s:%d Stack trace: #0 {main} diff --git a/Zend/tests/call_to_deprecated_function_args.phpt b/Zend/tests/call_to_deprecated_function_args.phpt index 5c3eb9ae16..c7781e30e0 100644 --- a/Zend/tests/call_to_deprecated_function_args.phpt +++ b/Zend/tests/call_to_deprecated_function_args.phpt @@ -1,5 +1,8 @@ --TEST-- Check that arguments are freed when calling a deprecated function +--SKIPIF-- +<?php +if (!extension_loaded('zend-test')) die('skip zend-test extension not loaded'); --FILE-- <?php @@ -8,20 +11,20 @@ set_error_handler(function($code, $msg) { }); try { - ezmlm_hash(new stdClass); + zend_test_deprecated(new stdClass); } catch (Error $e) { echo $e->getMessage(), "\n"; } $ret = new stdClass; try { - $ret = ezmlm_hash(new stdClass); + $ret = zend_test_deprecated(new stdClass()); } catch (Error $e) { echo $e->getMessage(), "\n"; } try { - $fn = 'ezmlm_hash'; + $fn = 'zend_test_deprecated'; $fn(new stdClass); } catch (Error $e) { echo $e->getMessage(), "\n"; @@ -29,7 +32,7 @@ try { $ret = new stdClass; try { - $fn = 'ezmlm_hash'; + $fn = 'zend_test_deprecated'; $ret = $fn(new stdClass); } catch (Error $e) { echo $e->getMessage(), "\n"; @@ -37,7 +40,7 @@ try { ?> --EXPECT-- -Function ezmlm_hash() is deprecated -Function ezmlm_hash() is deprecated -Function ezmlm_hash() is deprecated -Function ezmlm_hash() is deprecated +Function zend_test_deprecated() is deprecated +Function zend_test_deprecated() is deprecated +Function zend_test_deprecated() is deprecated +Function zend_test_deprecated() is deprecated diff --git a/Zend/tests/call_user_func_001.phpt b/Zend/tests/call_user_func_001.phpt index 15d0aec263..a6e43f3060 100644 --- a/Zend/tests/call_user_func_001.phpt +++ b/Zend/tests/call_user_func_001.phpt @@ -22,14 +22,20 @@ namespace testing { call_user_func(__NAMESPACE__ .'\foobar', 'foobar'); $class = __NAMESPACE__ .'\foo'; - call_user_func(array(new $class, 'priv'), 'foobar'); - call_user_func(array(new $class, 'prot'), 'foobar'); + try { + call_user_func(array(new $class, 'priv'), 'foobar'); + } catch (\TypeError $e) { + echo $e->getMessage(), "\n"; + } + try { + call_user_func(array(new $class, 'prot'), 'foobar'); + } catch (\TypeError $e) { + echo $e->getMessage(), "\n"; + } } ?> ---EXPECTF-- +--EXPECT-- string(6) "foobar" - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access private method testing\foo::priv() in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access protected method testing\foo::prot() in %s on line %d +call_user_func() expects parameter 1 to be a valid callback, cannot access private method testing\foo::priv() +call_user_func() expects parameter 1 to be a valid callback, cannot access protected method testing\foo::prot() diff --git a/Zend/tests/call_user_func_002.phpt b/Zend/tests/call_user_func_002.phpt index 454c6fda96..cc07ffab16 100644 --- a/Zend/tests/call_user_func_002.phpt +++ b/Zend/tests/call_user_func_002.phpt @@ -4,26 +4,38 @@ Testing call_user_func() with autoload and passing invalid params <?php spl_autoload_register(function ($class) { - var_dump($class); + var_dump($class); }); -call_user_func(array('foo', 'bar')); -call_user_func(array('', 'bar')); -call_user_func(array($foo, 'bar')); -call_user_func(array($foo, '')); +try { + call_user_func(array('foo', 'bar')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func(array('', 'bar')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func(array($foo, 'bar')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func(array($foo, '')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECTF-- string(3) "foo" +call_user_func() expects parameter 1 to be a valid callback, class 'foo' not found +call_user_func() expects parameter 1 to be a valid callback, class '' not found -Warning: call_user_func() expects parameter 1 to be a valid callback, class 'foo' not found in %s on line %d +Warning: Undefined variable: foo in %s on line %d +call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object -Warning: call_user_func() expects parameter 1 to be a valid callback, class '' not found in %s on line %d - -Notice: Undefined variable: foo in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d - -Notice: Undefined variable: foo in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d +Warning: Undefined variable: foo in %s on line %d +call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object diff --git a/Zend/tests/call_user_func_004.phpt b/Zend/tests/call_user_func_004.phpt deleted file mode 100644 index 7a2c4b8ffd..0000000000 --- a/Zend/tests/call_user_func_004.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Calling non-static method with call_user_func() ---FILE-- -<?php - -class foo { - public function teste() { - $this->a = 1; - } -} - -call_user_func(array('foo', 'teste')); - -?> ---EXPECTF-- -Deprecated: %son-static method foo::teste() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d -Stack trace: -#0 %s(%d): foo::teste() -#1 {main} - thrown in %s on line %d diff --git a/Zend/tests/call_user_func_005.phpt b/Zend/tests/call_user_func_005.phpt index 9305e5849c..13d69fd60d 100644 --- a/Zend/tests/call_user_func_005.phpt +++ b/Zend/tests/call_user_func_005.phpt @@ -9,7 +9,7 @@ class foo { return 1; } - public function teste() { + public static function teste() { return foo::x(function &($a=1,$b) { }); } } @@ -18,7 +18,6 @@ var_dump(call_user_func(array('foo', 'teste'))); ?> --EXPECTF-- -Deprecated: %son-static method foo::teste() should not be called statically in %s on line %d string(1) "x" array(1) { [0]=> diff --git a/Zend/tests/call_user_func_007.phpt b/Zend/tests/call_user_func_007.phpt index ed44320c3f..d3f2747c13 100644 --- a/Zend/tests/call_user_func_007.phpt +++ b/Zend/tests/call_user_func_007.phpt @@ -13,7 +13,7 @@ var_dump($a); --EXPECTF-- Notice: Undefined offset: 0 in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d Warning: Parameter 1 to foo() expected to be a reference, value given in %s on line %d array(0) { diff --git a/Zend/tests/call_user_func_array_invalid_type.phpt b/Zend/tests/call_user_func_array_invalid_type.phpt new file mode 100644 index 0000000000..d1c70f0fef --- /dev/null +++ b/Zend/tests/call_user_func_array_invalid_type.phpt @@ -0,0 +1,18 @@ +--TEST-- +call_user_func_array() generating TypeError +--FILE-- +<?php +class drv { + function func() { + } +} + +$drv = new drv; +try { + call_user_func_array(array($drv, 'func'), null); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +call_user_func_array() expects parameter 2 to be array, null given diff --git a/Zend/tests/case_insensitive_constant_deprecation.phpt b/Zend/tests/case_insensitive_constant_deprecation.phpt deleted file mode 100644 index e7a92c8c4c..0000000000 --- a/Zend/tests/case_insensitive_constant_deprecation.phpt +++ /dev/null @@ -1,127 +0,0 @@ ---TEST-- -Case-insensitive constants are deprecated ---FILE-- -<?php - -namespace { - define('FOO', 42, true); // Deprecated - define('NS\FOO', 24, true); // Deprecated - - var_dump(FOO); // Ok - var_dump(foo); // Deprecated - - var_dump(NS\FOO); // Ok - var_dump(ns\FOO); // Ok - var_dump(ns\foo); // Deprecated - - var_dump(defined('FOO')); // Ok - var_dump(defined('foo')); // Ok - var_dump(defined('NS\FOO')); // Ok - var_dump(defined('ns\FOO')); // Ok - var_dump(defined('ns\foo')); // Ok - - var_dump(constant('FOO')); // Ok - var_dump(constant('foo')); // Deprecated - var_dump(constant('NS\FOO')); // Ok - var_dump(constant('ns\FOO')); // Ok - var_dump(constant('ns\foo')); // Deprecated -} - -namespace NS { - var_dump(FOO); // Ok - var_dump(foo); // Deprecated -} - -namespace ns { - var_dump(FOO); // Ok - var_dump(foo); // Deprecated -} - -namespace Other { - var_dump(FOO); // Ok - var_dump(foo); // Deprecated - - var_dump(defined('FOO')); // Ok - var_dump(defined('foo')); // Ok - var_dump(defined('NS\FOO')); // Ok - var_dump(defined('ns\FOO')); // Ok - var_dump(defined('ns\foo')); // Ok - - var_dump(constant('FOO')); // Ok - var_dump(constant('foo')); // Deprecated - var_dump(constant('NS\FOO')); // Ok - var_dump(constant('ns\FOO')); // Ok - var_dump(constant('ns\foo')); // Deprecated - - const C1 = FOO; // Ok - var_dump(C1); - const C2 = foo; // Deprecated - var_dump(C2); - const C3 = 1 + FOO; // Ok - var_dump(C3); - const C4 = 1 + foo; // Deprecated - var_dump(C4); -} - -?> ---EXPECTF-- -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 4 - -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 5 -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 8 -int(42) -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 12 -int(24) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 21 -int(42) -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 24 -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 29 -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 34 -int(24) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 39 -int(42) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 48 -int(42) -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 51 -int(24) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 55 -int(42) -int(43) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 59 -int(43) diff --git a/Zend/tests/cast_to_string.phpt b/Zend/tests/cast_to_string.phpt Binary files differindex b3d245f1ed..cdff53c38f 100644 --- a/Zend/tests/cast_to_string.phpt +++ b/Zend/tests/cast_to_string.phpt diff --git a/Zend/tests/catch.phpt b/Zend/tests/catch.phpt index a83dd75baf..2e61fef935 100644 --- a/Zend/tests/catch.phpt +++ b/Zend/tests/catch.phpt @@ -1,5 +1,5 @@ --TEST-- -catch shouldn't call __autoload +catch shouldn't call autoloader --FILE-- <?php diff --git a/Zend/tests/class_exists_002.phpt b/Zend/tests/class_exists_002.phpt index ebe04575af..5e5df1d371 100644 --- a/Zend/tests/class_exists_002.phpt +++ b/Zend/tests/class_exists_002.phpt @@ -12,15 +12,11 @@ var_dump(class_exists(NULL)); var_dump(class_exists('FOO')); var_dump(class_exists('bar')); var_dump(class_exists(1)); -var_dump(class_exists(new stdClass)); ?> ---EXPECTF-- +--EXPECT-- bool(false) bool(false) bool(true) bool(false) bool(false) - -Warning: class_exists() expects parameter 1 to be string, object given in %s on line %d -NULL diff --git a/Zend/tests/class_name_as_scalar_error_002.phpt b/Zend/tests/class_name_as_scalar_error_002.phpt index cbea0c2dcc..ebb2dd4c27 100644 --- a/Zend/tests/class_name_as_scalar_error_002.phpt +++ b/Zend/tests/class_name_as_scalar_error_002.phpt @@ -11,9 +11,4 @@ namespace Foo\Bar { } ?> --EXPECTF-- -Deprecated: Cannot use "parent" when current class scope has no parent in %s on line %d - -Fatal error: Uncaught Error: Cannot use "parent" when current class scope has no parent in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d +Fatal error: Cannot use "parent" when current class scope has no parent in %s on line %d diff --git a/Zend/tests/class_properties_const.phpt b/Zend/tests/class_properties_const.phpt index 6f5471d20a..72b29519b4 100644 --- a/Zend/tests/class_properties_const.phpt +++ b/Zend/tests/class_properties_const.phpt @@ -13,13 +13,13 @@ var_dump($a->{1}); var_dump($a->{function(){}}); ?> --EXPECTF-- -Notice: Array to string conversion in %sclass_properties_const.php on line %d +Warning: Array to string conversion in %s on line %d runtime -Notice: Undefined property: A::$Array in %sclass_properties_const.php on line %d +Warning: Undefined property: A::$Array in %s on line %d NULL -Notice: Undefined property: A::$1 in %sclass_properties_const.php on line %d +Warning: Undefined property: A::$1 in %s on line %d NULL Fatal error: Uncaught Error: Object of class Closure could not be converted to string in %s:%d diff --git a/Zend/tests/clone_003.phpt b/Zend/tests/clone_003.phpt index 2dd376cf65..02ff350ca2 100644 --- a/Zend/tests/clone_003.phpt +++ b/Zend/tests/clone_003.phpt @@ -7,7 +7,7 @@ $a = clone $b; ?> --EXPECTF-- -Notice: Undefined variable: b in %s on line %d +Warning: Undefined variable: b in %s on line %d Fatal error: Uncaught Error: __clone method called on non-object in %s:%d Stack trace: diff --git a/Zend/tests/closure_012.phpt b/Zend/tests/closure_012.phpt index bae8f56878..f02045f5b1 100644 --- a/Zend/tests/closure_012.phpt +++ b/Zend/tests/closure_012.phpt @@ -16,8 +16,8 @@ $lambda(); var_dump($i); ?> --EXPECTF-- -Notice: Undefined variable: i in %sclosure_012.php on line 2 +Warning: Undefined variable: i in %s on line %d -Notice: Undefined variable: i in %sclosure_012.php on line 7 +Warning: Undefined variable: i in %s on line %d NULL int(2) diff --git a/Zend/tests/closure_025.phpt b/Zend/tests/closure_025.phpt deleted file mode 100644 index b3d03a7ad9..0000000000 --- a/Zend/tests/closure_025.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Closure 025: Using closure in create_function() ---FILE-- -<?php - -$a = create_function('$x', 'return function($y) use ($x) { return $x * $y; };'); - -var_dump($a(2)->__invoke(4)); - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -int(8) diff --git a/Zend/tests/closure_027.phpt b/Zend/tests/closure_027.phpt index 76754f9fba..9fc29a4f18 100644 --- a/Zend/tests/closure_027.phpt +++ b/Zend/tests/closure_027.phpt @@ -27,7 +27,7 @@ object(stdClass)#%d (0) { } NULL -Notice: Undefined variable: y in %s on line %d +Warning: Undefined variable: y in %s on line %d Exception: Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of Closure, instance of stdClass given, called in %s on line %d and defined in %s:%d diff --git a/Zend/tests/closure_034.phpt b/Zend/tests/closure_034.phpt index 8ba276a68a..27981a5c74 100644 --- a/Zend/tests/closure_034.phpt +++ b/Zend/tests/closure_034.phpt @@ -7,7 +7,6 @@ $a = function () use(&$a) {}; var_dump($a); ?> -===DONE=== --EXPECTF-- object(Closure)#%d (1) { ["static"]=> @@ -16,4 +15,3 @@ object(Closure)#%d (1) { *RECURSION* } } -===DONE=== diff --git a/Zend/tests/closure_040.phpt b/Zend/tests/closure_040.phpt index 231ab4081c..a5f52e70b0 100644 --- a/Zend/tests/closure_040.phpt +++ b/Zend/tests/closure_040.phpt @@ -25,21 +25,12 @@ $ca = $a->getIncrementor(); $cas = $a->getStaticIncrementor(); $ca->bindTo($a, array()); -$ca->bindTo(array(), 'A'); -$ca->bindTo($a, array(), ""); -$ca->bindTo(); $cas->bindTo($a, 'A'); ?> --EXPECTF-- -Notice: Array to string conversion in %s on line %d +Warning: Array to string conversion in %s on line %d Warning: Class 'Array' not found in %s on line %d -Warning: Closure::bindTo() expects parameter 1 to be object, array given in %s on line 25 - -Warning: Closure::bindTo() expects at most 2 parameters, 3 given in %s on line %d - -Warning: Closure::bindTo() expects at least 1 parameter, 0 given in %s on line %d - Warning: Cannot bind an instance to a static closure in %s on line %d diff --git a/Zend/tests/closure_041.phpt b/Zend/tests/closure_041.phpt index cfe4f9487f..42fc55dfe7 100644 --- a/Zend/tests/closure_041.phpt +++ b/Zend/tests/closure_041.phpt @@ -48,9 +48,7 @@ echo "After binding, no instance", "\n"; $d = $staticUnscoped->bindTo(null); $d(); echo "\n"; $d = $nonstaticUnscoped->bindTo(null); $d(); echo "\n"; $d = $staticScoped->bindTo(null); $d(); echo "\n"; -$d = $nonstaticScoped->bindTo(null); $d(); echo "\n"; -// $d is still non-static -$d->bindTo($d); +$d = $nonstaticScoped->bindTo(null); var_dump($d); echo "\n"; echo "After binding, with same-class instance for the bound ones", "\n"; $d = $staticUnscoped->bindTo(new A); @@ -81,9 +79,9 @@ bound: no scoped to A: bool(true) bound: no -Deprecated: Unbinding $this of closure is deprecated in %s on line %d -scoped to A: bool(true) -bound: no +Warning: Cannot unbind $this of closure using $this in %s on line %d +NULL + After binding, with same-class instance for the bound ones Warning: Cannot bind an instance to a static closure in %s on line %d diff --git a/Zend/tests/closure_044.phpt b/Zend/tests/closure_044.phpt index 225d7540d2..a848c0b17a 100644 --- a/Zend/tests/closure_044.phpt +++ b/Zend/tests/closure_044.phpt @@ -23,7 +23,7 @@ $nonstaticScoped(); echo "\n"; echo "After binding, null scope, no instance", "\n"; $d = $nonstaticUnscoped->bindTo(null, null); $d(); echo "\n"; -$d = $nonstaticScoped->bindTo(null, null); $d(); echo "\n"; +$d = $nonstaticScoped->bindTo(null, null); var_dump($d); echo "\n"; echo "After binding, null scope, with instance", "\n"; $d = $nonstaticUnscoped->bindTo(new A, null); $d(); echo "\n"; @@ -31,7 +31,7 @@ $d = $nonstaticScoped->bindTo(new A, null); $d(); echo "\n"; echo "After binding, with scope, no instance", "\n"; $d = $nonstaticUnscoped->bindTo(null, 'A'); $d(); echo "\n"; -$d = $nonstaticScoped->bindTo(null, 'A'); $d(); echo "\n"; +$d = $nonstaticScoped->bindTo(null, 'A'); var_dump($d); echo "\n"; echo "After binding, with scope, with instance", "\n"; $d = $nonstaticUnscoped->bindTo(new A, 'A'); $d(); echo "\n"; @@ -51,9 +51,8 @@ bool(false) bool(false) -Deprecated: Unbinding $this of closure is deprecated in %s on line %d -bool(false) -bool(false) +Warning: Cannot unbind $this of closure using $this in %s on line %d +NULL After binding, null scope, with instance bool(false) @@ -67,9 +66,8 @@ bool(true) bool(false) -Deprecated: Unbinding $this of closure is deprecated in %s on line %d -bool(true) -bool(false) +Warning: Cannot unbind $this of closure using $this in %s on line %d +NULL After binding, with scope, with instance bool(true) diff --git a/Zend/tests/closure_046.phpt b/Zend/tests/closure_046.phpt index e10cc1b57e..7d94df33b6 100644 --- a/Zend/tests/closure_046.phpt +++ b/Zend/tests/closure_046.phpt @@ -26,9 +26,7 @@ $nonstaticScoped(); echo "\n"; echo "After binding, no instance", "\n"; $d = $nonstaticUnscoped->bindTo(null, "static"); $d(); echo "\n"; -$d = $nonstaticScoped->bindTo(null, "static"); $d(); echo "\n"; -// $d is still non-static -$d->bindTo($d); +$d = $nonstaticScoped->bindTo(null, "static"); var_dump($d); echo "\n"; echo "After binding, with same-class instance for the bound one", "\n"; $d = $nonstaticUnscoped->bindTo(new A, "static"); $d(); echo "\n"; @@ -51,9 +49,8 @@ bool(false) bool(false) -Deprecated: Unbinding $this of closure is deprecated in %s on line %d -bool(true) -bool(false) +Warning: Cannot unbind $this of closure using $this in %s on line %d +NULL After binding, with same-class instance for the bound one bool(false) diff --git a/Zend/tests/closure_061.phpt b/Zend/tests/closure_061.phpt index f01e393570..2c574c49c0 100644 --- a/Zend/tests/closure_061.phpt +++ b/Zend/tests/closure_061.phpt @@ -175,9 +175,7 @@ Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure ------------------- bindTo(null, Cls::class): -Unbinding $this of a method is deprecated - -Success! +Cannot unbind $this of method bindTo(new Cls, Cls::class): Success! @@ -210,10 +208,10 @@ bindTo(new ClsUnrelated, SplDoublyLinkedList::class): Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated bindTo(null, null): -Cannot unbind $this of internal method +Cannot unbind $this of method bindTo(null, SplDoublyLinkedList::class): -Cannot unbind $this of internal method +Cannot unbind $this of method bindTo(new SplDoublyLinkedList, null): Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() diff --git a/Zend/tests/closure_062.phpt b/Zend/tests/closure_062.phpt index d56b4f0663..b8c0a981be 100644 --- a/Zend/tests/closure_062.phpt +++ b/Zend/tests/closure_062.phpt @@ -48,7 +48,7 @@ Test::staticMethod(); --EXPECTF-- instance scoped, non-static, $this used -Deprecated: Unbinding $this of closure is deprecated in %s on line %d +Warning: Cannot unbind $this of closure using $this in %s on line %d instance scoped, static, $this used instance scoped, non-static, $this not used static scoped, non-static, $this used diff --git a/Zend/tests/closures/closure_from_callable_basic.phpt b/Zend/tests/closures/closure_from_callable_basic.phpt index 0aacaf2ff5..d4c6427ae8 100644 --- a/Zend/tests/closures/closure_from_callable_basic.phpt +++ b/Zend/tests/closures/closure_from_callable_basic.phpt @@ -96,7 +96,6 @@ echo $fn(" OK".PHP_EOL); ?> -===DONE=== --EXPECT-- Access public static function OK Access public static function with different case OK @@ -118,4 +117,3 @@ Access public instance method of parent object through "self::" to parent method Access proteced instance method of parent object through "self::" to parent method OK MagicCall __call instance method __call,nonExistentMethod, OK MagicCall __callStatic static method __callStatic,nonExistentMethod, OK -===DONE=== diff --git a/Zend/tests/closures/closure_from_callable_error.phpt b/Zend/tests/closures/closure_from_callable_error.phpt index c6e4a7e0bb..5ada0ef2bf 100644 --- a/Zend/tests/closures/closure_from_callable_error.phpt +++ b/Zend/tests/closures/closure_from_callable_error.phpt @@ -193,7 +193,6 @@ catch (\Throwable $t) { echo "OK\n"; ?> -===DONE=== --EXPECT-- Cannot access privateInstance method statically Cannot access privateInstance method statically with colon scheme @@ -211,4 +210,3 @@ Function scope cannot closure over protected instance method Function scope cannot closure over private instance method Access private instance method of parent object through "self::" to parent method OK -===DONE=== diff --git a/Zend/tests/closures/closure_from_callable_non_static_statically.phpt b/Zend/tests/closures/closure_from_callable_non_static_statically.phpt index 17d39c052e..24df1d186a 100644 --- a/Zend/tests/closures/closure_from_callable_non_static_statically.phpt +++ b/Zend/tests/closures/closure_from_callable_non_static_statically.phpt @@ -17,4 +17,4 @@ try { ?> --EXPECT-- -Failed to create closure from callable: non-static method A::method() should not be called statically +Failed to create closure from callable: non-static method A::method() cannot be called statically diff --git a/Zend/tests/concat_001.phpt b/Zend/tests/concat_001.phpt index 1e657954a9..b8fad29674 100644 --- a/Zend/tests/concat_001.phpt +++ b/Zend/tests/concat_001.phpt @@ -50,24 +50,24 @@ var_dump($d.$d); echo "Done\n"; ?> --EXPECTF-- -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(24) "Arraythis is test object" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(16) "Arraysome string" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(8) "Array222" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(13) "Array2323.444" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(10) "ArrayArray" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(24) "this is test objectArray" string(30) "this is test objectsome string" string(22) "this is test object222" @@ -75,20 +75,20 @@ string(27) "this is test object2323.444" string(38) "this is test objectthis is test object" string(30) "some stringthis is test object" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(16) "some stringArray" string(14) "some string222" string(19) "some string2323.444" string(22) "some stringsome string" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(8) "222Array" string(22) "222this is test object" string(14) "222some string" string(11) "2222323.444" string(6) "222222" -Notice: Array to string conversion in %sconcat_001.php on line %d +Warning: Array to string conversion in %s on line %d string(13) "2323.444Array" string(27) "2323.444this is test object" string(19) "2323.444some string" diff --git a/Zend/tests/const_array_with_resource_key.phpt b/Zend/tests/const_array_with_resource_key.phpt index 0bf546af50..1e3dee4734 100644 --- a/Zend/tests/const_array_with_resource_key.phpt +++ b/Zend/tests/const_array_with_resource_key.phpt @@ -8,7 +8,7 @@ var_dump(FOO); ?> --EXPECTF-- -Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d array(1) { [%d]=> int(42) diff --git a/Zend/tests/constant_expressions_classes.phpt b/Zend/tests/constant_expressions_classes.phpt index eed006bfe1..89cabc0f91 100644 --- a/Zend/tests/constant_expressions_classes.phpt +++ b/Zend/tests/constant_expressions_classes.phpt @@ -4,8 +4,6 @@ Constant scalar expressions with autoloading and classes opcache.enable=1 opcache.enable_cli=1 opcache.optimization_level=-1 ---SKIPIF-- -<?php if (php_sapi_name() != "cli") die("skip CLI only"); ?> --FILE-- <?php diff --git a/Zend/tests/constant_expressions_invalid_offset_type_error.phpt b/Zend/tests/constant_expressions_invalid_offset_type_error.phpt index 52d2194e26..649c3a325a 100644 --- a/Zend/tests/constant_expressions_invalid_offset_type_error.phpt +++ b/Zend/tests/constant_expressions_invalid_offset_type_error.phpt @@ -8,7 +8,7 @@ const C2 = [C1, [] => 1]; ?> --EXPECTF-- -Fatal error: Uncaught Error: Illegal offset type in %s:%d +Fatal error: Uncaught TypeError: Illegal offset type in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/Zend/tests/constants_002.phpt b/Zend/tests/constants_002.phpt index b0cf1db61f..ddb2e67307 100644 --- a/Zend/tests/constants_002.phpt +++ b/Zend/tests/constants_002.phpt @@ -4,7 +4,11 @@ Defining constants with non-scalar values <?php define('foo', new stdClass); -var_dump(foo); +try { + var_dump(foo); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} define('foo', fopen(__FILE__, 'r')); var_dump(foo); @@ -12,7 +16,5 @@ var_dump(foo); ?> --EXPECTF-- Warning: Constants may only evaluate to scalar values, arrays or resources in %s on line %d - -Warning: Use of undefined constant foo - assumed 'foo' (this will throw an Error in a future version of PHP) in %s on line %d -string(%d) "foo" -resource(%d) of type (stream) +Undefined constant 'foo' +resource(5) of type (stream) diff --git a/Zend/tests/constants_005.phpt b/Zend/tests/constants_005.phpt index b5a3a6bd38..27ab0259d1 100644 --- a/Zend/tests/constants_005.phpt +++ b/Zend/tests/constants_005.phpt @@ -2,11 +2,10 @@ Persistent case insensitive and user defined constants --FILE-- <?php -var_dump(ZEND_THREAD_safe); +var_dump(defined('ZEND_THREAD_safe')); define("ZEND_THREAD_safe", 123); var_dump(ZEND_THREAD_safe); ?> ---EXPECTF-- -Warning: Use of undefined constant ZEND_THREAD_safe - assumed 'ZEND_THREAD_safe' (this will throw an Error in a future version of PHP) in %s on line %d -string(16) "ZEND_THREAD_safe" +--EXPECT-- +bool(false) int(123) diff --git a/Zend/tests/custom_assert_deprecation.phpt b/Zend/tests/custom_assert_forbidden.phpt index b4e22843dd..492a656f39 100644 --- a/Zend/tests/custom_assert_deprecation.phpt +++ b/Zend/tests/custom_assert_forbidden.phpt @@ -9,4 +9,4 @@ function assert() {} ?> --EXPECTF-- -Deprecated: Defining a custom assert() function is deprecated, as the function has special semantics in %s on line %d +Fatal error: Defining a custom assert() function is not allowed, as the function has special semantics in %s on line %d diff --git a/Zend/tests/defined_fn_no_ns_fallback.phpt b/Zend/tests/defined_fn_no_ns_fallback.phpt new file mode 100644 index 0000000000..6dc2b51ed6 --- /dev/null +++ b/Zend/tests/defined_fn_no_ns_fallback.phpt @@ -0,0 +1,16 @@ +--TEST-- +There should be no namespace fallback when using the defined() function +--FILE-- +<?php + +namespace Foo; + +var_dump(\defined('Foo\PHP_INT_MAX')); + +$const = 'Foo\PHP_INT_MAX'; +var_dump(\defined($const)); + +?> +--EXPECT-- +bool(false) +bool(false) diff --git a/Zend/tests/dereference_002.phpt b/Zend/tests/dereference_002.phpt index 7290df7714..e17e5e85b6 100644 --- a/Zend/tests/dereference_002.phpt +++ b/Zend/tests/dereference_002.phpt @@ -70,7 +70,7 @@ array(2) { } int(1) -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL Notice: Undefined offset: 4 in %s on line %d diff --git a/Zend/tests/dereference_007.phpt b/Zend/tests/dereference_007.phpt index e7df6a422d..afe6e9d5b2 100644 --- a/Zend/tests/dereference_007.phpt +++ b/Zend/tests/dereference_007.phpt @@ -33,5 +33,5 @@ print "ok\n"; ?> --EXPECTF-- -Notice: Undefined variable: x in %s on line %d +Warning: Undefined variable: x in %s on line %d ok diff --git a/Zend/tests/dereference_010.phpt b/Zend/tests/dereference_010.phpt index c63f6acaf9..c916352afa 100644 --- a/Zend/tests/dereference_010.phpt +++ b/Zend/tests/dereference_010.phpt @@ -21,10 +21,10 @@ var_dump(b()[1]); ?> --EXPECTF-- -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d diff --git a/Zend/tests/dereference_014.phpt b/Zend/tests/dereference_014.phpt index 189dca7a38..470c233a19 100644 --- a/Zend/tests/dereference_014.phpt +++ b/Zend/tests/dereference_014.phpt @@ -27,12 +27,12 @@ var_dump($h); ?> --EXPECTF-- -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to get property 'a' of non-object in %s on line %d +Warning: Trying to get property 'a' of non-object in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to get property 'b' of non-object in %s on line %d +Warning: Trying to get property 'b' of non-object in %s on line %d NULL diff --git a/Zend/tests/dynamic_call_001.phpt b/Zend/tests/dynamic_call_001.phpt deleted file mode 100644 index 7f8a6c0b3d..0000000000 --- a/Zend/tests/dynamic_call_001.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Testing dynamic call to constructor (old-style) ---FILE-- -<?php - -class foo { - public function foo() { - } -} - -$a = 'foo'; - -$a::$a(); - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in %s on line %d - -Fatal error: Uncaught Error: Non-static method foo::foo() cannot be called statically in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d diff --git a/Zend/tests/dynamic_call_004.phpt b/Zend/tests/dynamic_call_004.phpt index 2f444b3ee6..9028b1c801 100644 --- a/Zend/tests/dynamic_call_004.phpt +++ b/Zend/tests/dynamic_call_004.phpt @@ -7,7 +7,7 @@ $a::$b(); ?> --EXPECTF-- -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d Fatal error: Uncaught Error: Class name must be a valid object or a string in %s:%d Stack trace: diff --git a/Zend/tests/dynamic_call_005.phpt b/Zend/tests/dynamic_call_005.phpt index 840e298b82..91d1cb914c 100644 --- a/Zend/tests/dynamic_call_005.phpt +++ b/Zend/tests/dynamic_call_005.phpt @@ -6,24 +6,31 @@ Dynamic calls to scope introspection functions are forbidden function test_calls($func) { $i = 1; - array_map($func, [['i' => new stdClass]]); - var_dump($i); + try { + array_map($func, [['i' => new stdClass]]); + var_dump($i); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } - $func(['i' => new stdClass]); - var_dump($i); + try { + $func(['i' => new stdClass]); + var_dump($i); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } - call_user_func($func, ['i' => new stdClass]); - var_dump($i); + try { + call_user_func($func, ['i' => new stdClass]); + var_dump($i); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } } test_calls('extract'); ?> ---EXPECTF-- -Warning: Cannot call extract() dynamically in %s on line %d -int(1) - -Warning: Cannot call extract() dynamically in %s on line %d -int(1) - -Warning: Cannot call extract() dynamically in %s on line %d -int(1) +--EXPECT-- +Cannot call extract() dynamically +Cannot call extract() dynamically +Cannot call extract() dynamically diff --git a/Zend/tests/dynamic_call_006.phpt b/Zend/tests/dynamic_call_006.phpt index 058e22fda0..e6ea719158 100644 --- a/Zend/tests/dynamic_call_006.phpt +++ b/Zend/tests/dynamic_call_006.phpt @@ -3,46 +3,56 @@ Dynamic calls to scope introspection functions are forbidden (function variation --FILE-- <?php function test() { - $func = 'extract'; - $func(['a' => 'b']); - $func = 'compact'; - $func(['a']); - - $func = 'parse_str'; - $func('a=b'); - - $func = 'get_defined_vars'; - $func(); - - $func = 'assert'; - $func('1==2'); - - $func = 'func_get_args'; - $func(); - - $func = 'func_get_arg'; - $func(1); - - $func = 'func_num_args'; - $func(); + try { + $func = 'extract'; + $func(['a' => 'b']); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } + + try { + $func = 'compact'; + $func(['a']); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } + + try { + $func = 'get_defined_vars'; + $func(); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } + + try { + $func = 'func_get_args'; + $func(); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } + + try { + $func = 'func_get_arg'; + $func(1); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } + + try { + $func = 'func_num_args'; + $func(); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } } test(); ?> ---EXPECTF-- -Warning: Cannot call extract() dynamically in %s on line %d - -Warning: Cannot call compact() dynamically in %s on line %d - -Warning: Cannot call parse_str() with a single argument dynamically in %s on line %d - -Warning: Cannot call get_defined_vars() dynamically in %s on line %d - -Warning: Cannot call assert() with string argument dynamically in %s on line %d - -Warning: Cannot call func_get_args() dynamically in %s on line %d - -Warning: Cannot call func_get_arg() dynamically in %s on line %d - -Warning: Cannot call func_num_args() dynamically in %s on line %d +--EXPECT-- +Cannot call extract() dynamically +Cannot call compact() dynamically +Cannot call get_defined_vars() dynamically +Cannot call func_get_args() dynamically +Cannot call func_get_arg() dynamically +Cannot call func_num_args() dynamically diff --git a/Zend/tests/dynamic_call_007.phpt b/Zend/tests/dynamic_call_007.phpt index 61ae182914..f1312b95b4 100644 --- a/Zend/tests/dynamic_call_007.phpt +++ b/Zend/tests/dynamic_call_007.phpt @@ -5,13 +5,17 @@ Dynamic calls to scope introspection functions are forbidden (misoptimization) function test() { $i = 1; - array_map('extract', [['i' => new stdClass]]); + try { + array_map('extract', [['i' => new stdClass]]); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } $i += 1; var_dump($i); } test(); ?> ---EXPECTF-- -Warning: Cannot call extract() dynamically in %s on line %d +--EXPECT-- +Cannot call extract() dynamically int(2) diff --git a/Zend/tests/dynamic_call_008.phpt b/Zend/tests/dynamic_call_008.phpt index 24240472d1..1916bcf913 100644 --- a/Zend/tests/dynamic_call_008.phpt +++ b/Zend/tests/dynamic_call_008.phpt @@ -4,10 +4,14 @@ Don't optimize dynamic call to non-dynamic one if it drops the warning <?php function test() { - ((string) 'extract')(['a' => 42]); + try { + ((string) 'extract')(['a' => 42]); + } catch (\Error $e) { + echo $e->getMessage() . "\n"; + } } test(); ?> ---EXPECTF-- -Warning: Cannot call extract() dynamically in %s on line %d +--EXPECT-- +Cannot call extract() dynamically diff --git a/Zend/tests/dynamic_prop_name_leak.phpt b/Zend/tests/dynamic_prop_name_leak.phpt new file mode 100644 index 0000000000..093a42400d --- /dev/null +++ b/Zend/tests/dynamic_prop_name_leak.phpt @@ -0,0 +1,13 @@ +--TEST-- +Dynamic prop name with type conversion in reference position should not leak +--FILE-- +<?php +$obj = new stdClass; +$name = 0.0; +$ref =& $obj->$name; +var_dump($obj); +--EXPECT-- +object(stdClass)#1 (1) { + ["0"]=> + &NULL +} diff --git a/Zend/tests/each_001.phpt b/Zend/tests/each_001.phpt deleted file mode 100644 index f2cae3d875..0000000000 --- a/Zend/tests/each_001.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -Testing each() with an undefined variable ---FILE-- -<?php - -each($foo); - -?> ---EXPECTF-- -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d - -Warning: Variable passed to each() is not an array or object in %s on line %d diff --git a/Zend/tests/each_002.phpt b/Zend/tests/each_002.phpt deleted file mode 100644 index 5454f5ce0f..0000000000 --- a/Zend/tests/each_002.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Testing each() with array and object ---FILE-- -<?php - -$a = new stdClass; -$foo = each($a); -var_dump($foo); - -$a = new stdClass; -var_dump(each($a)); - -$a = array(new stdClass); -var_dump(each($a)); - - -?> ---EXPECTF-- -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d -bool(false) -bool(false) -array(4) { - [1]=> - object(stdClass)#1 (0) { - } - ["value"]=> - object(stdClass)#1 (0) { - } - [0]=> - int(0) - ["key"]=> - int(0) -} diff --git a/Zend/tests/each_003.phpt b/Zend/tests/each_003.phpt deleted file mode 100644 index d0038c0561..0000000000 --- a/Zend/tests/each_003.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Testing each() with recursion ---INI-- -zend.enable_gc=1 ---FILE-- -<?php - -$a = array(array()); -$a[] =& $a; - -var_dump(each($a[1])); - -?> ---EXPECTF-- -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d -array(4) { - [1]=> - array(0) { - } - ["value"]=> - array(0) { - } - [0]=> - int(0) - ["key"]=> - int(0) -} diff --git a/Zend/tests/entry_block_with_predecessors.phpt b/Zend/tests/entry_block_with_predecessors.phpt index ffc3147f1c..45c3302fc0 100644 --- a/Zend/tests/entry_block_with_predecessors.phpt +++ b/Zend/tests/entry_block_with_predecessors.phpt @@ -28,6 +28,6 @@ test2(); ?> --EXPECTF-- -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d int(1) int(2) diff --git a/Zend/tests/errmsg_012.phpt b/Zend/tests/errmsg_012.phpt deleted file mode 100644 index c914125af5..0000000000 --- a/Zend/tests/errmsg_012.phpt +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -errmsg: __autoload() must take exactly 1 argument ---FILE-- -<?php - -function __autoload($a, $b) {} - -echo "Done\n"; -?> ---EXPECTF-- -Fatal error: __autoload() must take exactly 1 argument in %s on line %d diff --git a/Zend/tests/errmsg_013.phpt b/Zend/tests/errmsg_013.phpt index 606282458b..037ef9b1aa 100644 --- a/Zend/tests/errmsg_013.phpt +++ b/Zend/tests/errmsg_013.phpt @@ -11,4 +11,4 @@ class test { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Default value for parameters with array type can only be an array or NULL in %s on line %d +Fatal error: Cannot use string as default value for parameter $a of type array in %s on line %d diff --git a/Zend/tests/errmsg_045.phpt b/Zend/tests/errmsg_045.phpt index fbb2528e28..6311eb30e5 100644 --- a/Zend/tests/errmsg_045.phpt +++ b/Zend/tests/errmsg_045.phpt @@ -10,11 +10,11 @@ set_error_handler(function($_, $msg, $file) { /* This is just a particular example of a non-fatal compile-time error * If this breaks in future, just find another example and use it instead */ -eval('class A { function test() { } } class B extends A { function test($a) { } }'); +eval('class A { private function __invoke() { } }'); ?> --EXPECTF-- -string(62) "Declaration of B::test($a) should be compatible with A::test()" +string(76) "The magic method __invoke() must have public visibility and cannot be static" string(%d) "%s(%d) : eval()'d code" -Notice: Undefined variable: undefined in %s on line %d +Warning: Undefined variable: undefined in %s on line %d diff --git a/Zend/tests/error_reporting03.phpt b/Zend/tests/error_reporting03.phpt index f344e9557b..b4fbbecca8 100644 --- a/Zend/tests/error_reporting03.phpt +++ b/Zend/tests/error_reporting03.phpt @@ -30,6 +30,6 @@ var_dump(error_reporting()); echo "Done\n"; ?> --EXPECTF-- -Notice: Undefined variable: undef2 in %s on line %d +Warning: Undefined variable: undef2 in %s on line %d int(32767) Done diff --git a/Zend/tests/error_reporting04.phpt b/Zend/tests/error_reporting04.phpt index 5b476cdf7f..7cd555716a 100644 --- a/Zend/tests/error_reporting04.phpt +++ b/Zend/tests/error_reporting04.phpt @@ -18,6 +18,6 @@ var_dump(error_reporting()); echo "Done\n"; ?> --EXPECTF-- -Notice: Undefined variable: undef in %s on line %d +Warning: Undefined variable: undef in %s on line %d int(32767) Done diff --git a/Zend/tests/error_reporting05.phpt b/Zend/tests/error_reporting05.phpt index 6ea76fda3e..9c1a7c48d6 100644 --- a/Zend/tests/error_reporting05.phpt +++ b/Zend/tests/error_reporting05.phpt @@ -27,8 +27,8 @@ var_dump(error_reporting()); echo "Done\n"; ?> --EXPECTF-- -Notice: Undefined variable: undef_value in %s on line %d +Warning: Undefined variable: undef_value in %s on line %d -Notice: Undefined variable: undef_name in %s on line %d +Warning: Undefined variable: undef_name in %s on line %d int(32767) Done diff --git a/Zend/tests/error_reporting08.phpt b/Zend/tests/error_reporting08.phpt index 32cb6b8d16..868c879160 100644 --- a/Zend/tests/error_reporting08.phpt +++ b/Zend/tests/error_reporting08.phpt @@ -27,6 +27,6 @@ var_dump(error_reporting()); echo "Done\n"; ?> --EXPECTF-- -Notice: Undefined variable: undef3 in %s on line %d +Warning: Undefined variable: undef3 in %s on line %d int(32767) Done diff --git a/Zend/tests/error_reporting09.phpt b/Zend/tests/error_reporting09.phpt index 3d723f36c0..287c25460f 100644 --- a/Zend/tests/error_reporting09.phpt +++ b/Zend/tests/error_reporting09.phpt @@ -24,8 +24,8 @@ var_dump(error_reporting()); echo "Done\n"; ?> --EXPECTF-- -Notice: Undefined variable: blah in %s on line %d +Warning: Undefined variable: blah in %s on line %d -Notice: Undefined variable: undef2 in %s on line %d +Warning: Undefined variable: undef2 in %s on line %d int(32767) Done diff --git a/Zend/tests/error_reporting10.phpt b/Zend/tests/error_reporting10.phpt index 8b0c7b9923..c18c04d8f0 100644 --- a/Zend/tests/error_reporting10.phpt +++ b/Zend/tests/error_reporting10.phpt @@ -8,7 +8,6 @@ error_reporting(E_ALL); function make_exception() { @$blah; - str_replace(); error_reporting(0); throw new Exception(); } diff --git a/Zend/tests/exception_012.phpt b/Zend/tests/exception_012.phpt deleted file mode 100644 index 4a1070330a..0000000000 --- a/Zend/tests/exception_012.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Test exception doesn't cause RSHUTDOWN bypass, variation 1 ---INI-- -assert.bail=1 -assert.exception=1 ---FILE-- -<?php - -$func = create_function('', 'define("Mommy", 1); assert(false);'); -$func(); - -?> ---EXPECTHEADERS-- -Content-type: text/html; charset=UTF-8 ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d - -Fatal error: Uncaught AssertionError: assert(false) in %sexception_012.php(%d) : runtime-created function:%d -Stack trace: -#0 %sexception_012.php(%d) : runtime-created function(%d): assert(false, 'assert(false)') -#1 %sexception_012.php(%d): __lambda_func() -#2 {main} - thrown in %sexception_012.php(%d) : runtime-created function on line %d diff --git a/Zend/tests/exception_017.phpt b/Zend/tests/exception_017.phpt index 8d87ec6ee9..77fbf2d844 100644 --- a/Zend/tests/exception_017.phpt +++ b/Zend/tests/exception_017.phpt @@ -12,27 +12,29 @@ function foo(callable $x) { try { C::foo(); } catch (Error $e) { - echo "\nException: " . $e->getMessage() . " in " , $e->getFile() . " on line " . $e->getLine() . "\n"; + echo $e, "\n\n"; } try { foo("C::foo"); } catch (Error $e) { - echo "\n"; - do { - echo "Exception: " . $e->getMessage() . "\n"; - $e = $e->getPrevious(); - } while ($e instanceof Error); + echo $e, "\n\n"; } C::foo(); ?> --EXPECTF-- -Exception: Cannot call abstract method C::foo() in %sexception_017.php on line %d +Error: Cannot call abstract method C::foo() in %s:%d +Stack trace: +#0 {main} + +TypeError: Argument 1 passed to foo() must be callable, string given, called in %s on line %d and defined in %s:%d +Stack trace: +#0 %s(%d): foo('C::foo') +#1 {main} -Exception: Argument 1 passed to foo() must be callable, string given, called in %s on line %d -Fatal error: Uncaught Error: Cannot call abstract method C::foo() in %sexception_017.php:%d +Fatal error: Uncaught Error: Cannot call abstract method C::foo() in %s:%d Stack trace: #0 {main} - thrown in %sexception_017.php on line %d + thrown in %s on line %d diff --git a/Zend/tests/exception_handler_004.phpt b/Zend/tests/exception_handler_004.phpt index 69a4136b08..6552141b73 100644 --- a/Zend/tests/exception_handler_004.phpt +++ b/Zend/tests/exception_handler_004.phpt @@ -5,8 +5,6 @@ exception handler tests - 4 set_exception_handler("fo"); set_exception_handler(array("", "")); -set_exception_handler(); -set_exception_handler("foo", "bar"); echo "Done\n"; ?> @@ -14,8 +12,4 @@ echo "Done\n"; Warning: set_exception_handler() expects the argument (fo) to be a valid callback in %s on line %d Warning: set_exception_handler() expects the argument (::) to be a valid callback in %s on line %d - -Warning: set_exception_handler() expects exactly 1 parameter, 0 given in %s on line %d - -Warning: set_exception_handler() expects exactly 1 parameter, 2 given in %s on line %d Done diff --git a/Zend/tests/foreach_undefined.phpt b/Zend/tests/foreach_undefined.phpt index aa4a160e6c..bc1d8bbc71 100644 --- a/Zend/tests/foreach_undefined.phpt +++ b/Zend/tests/foreach_undefined.phpt @@ -8,7 +8,7 @@ foreach($a as $val); echo "Done\n"; ?> --EXPECTF-- -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d Warning: Invalid argument supplied for foreach() in %s on line %d Done diff --git a/Zend/tests/fr47160.phpt b/Zend/tests/fr47160.phpt index 786183c0c1..6567804902 100644 --- a/Zend/tests/fr47160.phpt +++ b/Zend/tests/fr47160.phpt @@ -36,20 +36,6 @@ class Magic3 { } } -$f = array('Hello','world'); -try { - var_dump($f('you')); -} catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} -try { - var_dump(call_user_func($f, 'you')); -} catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} - -printf("-----\n"); - $h= new Hello; $f = array($h,'world'); var_dump($f('again')); @@ -107,14 +93,6 @@ var_dump(call_user_func($f, 'you')); ?> --EXPECTF-- -Deprecated: Non-static method Hello::world() should not be called statically in %s on line %d -Hello, you -Exception: Using $this when not in object context - -Deprecated: %son-static method Hello::world() should not be called statically in %s on line %d -Hello, you -Exception: Using $this when not in object context ------ Hello, again object(Hello)#%d (0) { } diff --git a/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt b/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt index a8ba71c0bf..5c0770ff65 100644 --- a/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt +++ b/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt @@ -2,9 +2,10 @@ Call internal function with incorrect number of arguments --FILE-- <?php -substr("foo"); -array_diff([]); ---EXPECTF-- -Warning: substr() expects at least 2 parameters, 1 given in %s - -Warning: array_diff(): at least 2 parameters are required, 1 given in %s +try { + substr("foo"); +} catch (ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +--EXPECT-- +substr() expects at least 2 parameters, 1 given diff --git a/Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt b/Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt index 8775bece88..2134dfe0f6 100644 --- a/Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt +++ b/Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt @@ -5,14 +5,19 @@ Call internal function with incorrect number of arguments with strict types declare(strict_types=1); try { substr("foo"); -} catch (\Error $e) { +} catch (ArgumentCountError $e) { echo get_class($e) . PHP_EOL; echo $e->getMessage() . PHP_EOL; } -array_diff([]); ---EXPECTF-- +try { + array_diff([]); +} catch (ArgumentCountError $e) { + echo get_class($e) . PHP_EOL; + echo $e->getMessage(), "\n"; +} +--EXPECT-- ArgumentCountError substr() expects at least 2 parameters, 1 given - -Warning: array_diff(): at least 2 parameters are required, 1 given in %s +ArgumentCountError +At least 2 parameters are required, 1 given diff --git a/Zend/tests/function_exists_basic.phpt b/Zend/tests/function_exists_basic.phpt index 5832231551..5125350d8d 100644 --- a/Zend/tests/function_exists_basic.phpt +++ b/Zend/tests/function_exists_basic.phpt @@ -28,7 +28,6 @@ Class C { } var_dump(function_exists('C::f')); ?> -===Done=== --EXPECT-- *** Testing function_exists() : basic functionality *** Internal function: bool(true) @@ -36,4 +35,3 @@ User defined function: bool(true) Case sensitivity: bool(true) Non existent function: bool(false) Method: bool(false) -===Done=== diff --git a/Zend/tests/generators/throw_not_an_exception.phpt b/Zend/tests/generators/throw_not_an_exception.phpt index 920d8eb847..abf9a3c894 100644 --- a/Zend/tests/generators/throw_not_an_exception.phpt +++ b/Zend/tests/generators/throw_not_an_exception.phpt @@ -12,9 +12,8 @@ $gen->throw(new stdClass); ?> --EXPECTF-- -Fatal error: Uncaught Error: Cannot throw objects that do not implement Throwable in %s:%d +Fatal error: Uncaught TypeError: Generator::throw() expects parameter 1 to be Throwable, object given in %s:%d Stack trace: -#0 [internal function]: gen() -#1 %s(%d): Generator->throw(Object(stdClass)) -#2 {main} +#0 %s(%d): Generator->throw(Object(stdClass)) +#1 {main} thrown in %s on line %d diff --git a/Zend/tests/get_class_vars_002.phpt b/Zend/tests/get_class_vars_002.phpt index 23531e458d..475545ffe7 100644 --- a/Zend/tests/get_class_vars_002.phpt +++ b/Zend/tests/get_class_vars_002.phpt @@ -41,9 +41,9 @@ array(3) { int(6) } -Notice: Undefined property: C::$b in %s on line %d +Warning: Undefined property: C::$b in %s on line %d -Notice: Undefined property: C::$c in %s on line %d +Warning: Undefined property: C::$c in %s on line %d int(1) NULL NULL diff --git a/Zend/tests/get_defined_functions_basic.phpt b/Zend/tests/get_defined_functions_basic.phpt index f782b90892..1ea5df7ec7 100644 --- a/Zend/tests/get_defined_functions_basic.phpt +++ b/Zend/tests/get_defined_functions_basic.phpt @@ -52,8 +52,6 @@ if (count($user) == 2 && in_array("foo", $user) && in_array("helloworld", $user) } ?> -===Done=== --EXPECT-- *** Testing get_defined_functions() : basic functionality *** TEST PASSED -===Done=== diff --git a/Zend/tests/globals_001.phpt b/Zend/tests/globals_001.phpt index 9a9c5401fe..821f345b81 100644 --- a/Zend/tests/globals_001.phpt +++ b/Zend/tests/globals_001.phpt @@ -29,6 +29,6 @@ string(%d) "%s" Notice: Undefined index: PHP_SELF in %s on line %d NULL -Notice: Undefined variable: _SERVER in %s on line %d +Warning: Undefined variable: _SERVER in %s on line %d NULL Done diff --git a/Zend/tests/globals_002.phpt b/Zend/tests/globals_002.phpt index d57e350092..f2f53a13f5 100644 --- a/Zend/tests/globals_002.phpt +++ b/Zend/tests/globals_002.phpt @@ -32,6 +32,6 @@ string(%d) "%s" Notice: Undefined index: PHP_SELF in %s on line %d NULL -Notice: Undefined variable: _SERVER in %s on line %d +Warning: Undefined variable: _SERVER in %s on line %d NULL Done diff --git a/Zend/tests/globals_003.phpt b/Zend/tests/globals_003.phpt index cdd4d211af..24e8edd8aa 100644 --- a/Zend/tests/globals_003.phpt +++ b/Zend/tests/globals_003.phpt @@ -38,6 +38,6 @@ string(%d) "%s" Notice: Undefined index: PHP_SELF in %s on line %d NULL -Notice: Undefined variable: _SERVER in %s on line %d +Warning: Undefined variable: _SERVER in %s on line %d NULL Done diff --git a/Zend/tests/globals_004.phpt b/Zend/tests/globals_004.phpt index 0f2f7f0764..9ba3866835 100644 --- a/Zend/tests/globals_004.phpt +++ b/Zend/tests/globals_004.phpt @@ -23,6 +23,6 @@ string(%d) "%s" Notice: Undefined index: PHP_SELF in %s on line %d NULL -Notice: Undefined variable: _SERVER in %s on line %d +Warning: Undefined variable: _SERVER in %s on line %d NULL Done diff --git a/Zend/tests/halt_compiler2.phpt b/Zend/tests/halt_compiler2.phpt index a89274a804..09af8b2a03 100644 --- a/Zend/tests/halt_compiler2.phpt +++ b/Zend/tests/halt_compiler2.phpt @@ -11,7 +11,6 @@ file_put_contents(__DIR__ . '/test2.php', $text); include __DIR__ . '/test1.php'; include __DIR__ . '/test2.php'; ?> -==DONE== --CLEAN-- <?php unlink(__DIR__ . '/test1.php'); @@ -20,4 +19,3 @@ unlink(__DIR__ . '/test2.php'); --EXPECT-- testint(73) test2int(74) -==DONE== diff --git a/Zend/tests/halt_compiler3.phpt b/Zend/tests/halt_compiler3.phpt index 7bd7410c73..f0a5323e66 100644 --- a/Zend/tests/halt_compiler3.phpt +++ b/Zend/tests/halt_compiler3.phpt @@ -4,7 +4,5 @@ __HALT_COMPILER(); bad define() of __COMPILER_HALT_OFFSET__ 1 <?php define ('__COMPILER_HALT_OFFSET__', 1); ?> -==DONE== --EXPECTF-- Notice: Constant __COMPILER_HALT_OFFSET__ already defined in %s on line %d -==DONE== diff --git a/Zend/tests/halt_compiler5.phpt b/Zend/tests/halt_compiler5.phpt index 71d973e4f7..51167b6c3b 100644 --- a/Zend/tests/halt_compiler5.phpt +++ b/Zend/tests/halt_compiler5.phpt @@ -5,4 +5,7 @@ Using __COMPILER_HALF_OFFSET__ with trailing {} (OSS-Fuzz #17895) __COMPILER_HALT_OFFSET__; {} --EXPECTF-- -Warning: Use of undefined constant __COMPILER_HALT_OFFSET__ - assumed '__COMPILER_HALT_OFFSET__' (this will throw an Error in a future version of PHP) in %s on line %d +Fatal error: Uncaught Error: Undefined constant '__COMPILER_HALT_OFFSET__' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/illegal_offset_unset_isset_empty.phpt b/Zend/tests/illegal_offset_unset_isset_empty.phpt new file mode 100644 index 0000000000..9005053e67 --- /dev/null +++ b/Zend/tests/illegal_offset_unset_isset_empty.phpt @@ -0,0 +1,27 @@ +--TEST-- +Using unset(), isset(), empty() with an illegal array offset throws +--FILE-- +<?php + +$ary = []; +try { + unset($ary[[]]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + isset($ary[[]]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + empty($ary[[]]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Illegal offset type in unset +Illegal offset type in isset or empty +Illegal offset type in isset or empty diff --git a/Zend/tests/incompat_ctx_user.phpt b/Zend/tests/incompat_ctx_user.phpt index 25c95ba219..8c7461e4f7 100644 --- a/Zend/tests/incompat_ctx_user.phpt +++ b/Zend/tests/incompat_ctx_user.phpt @@ -4,18 +4,17 @@ Incompatible context call (non-internal function) <?php class A { - function foo() { var_dump(get_class($this)); } + function foo() { var_dump(get_class($this)); } } class B { - function bar() { A::foo(); } + function bar() { A::foo(); } } $b = new B; try { - $b->bar(); + $b->bar(); } catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; + echo "Exception: " . $e->getMessage() . "\n"; } ?> --EXPECTF-- -Deprecated: Non-static method A::foo() should not be called statically in %s on line %d -Exception: Using $this when not in object context +Exception: Non-static method A::foo() cannot be called statically diff --git a/Zend/tests/indexing_001.phpt b/Zend/tests/indexing_001.phpt index f247a420b5..453b5ca86f 100644 --- a/Zend/tests/indexing_001.phpt +++ b/Zend/tests/indexing_001.phpt @@ -7,32 +7,48 @@ $array=array(1); $testvalues=array(null, 0, 1, true, false,'',' ',0.1,array()); foreach ($testvalues as $testvalue) { - $testvalue['foo']=$array; - var_dump ($testvalue); + try { + $testvalue['foo']=$array; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump($testvalue); } echo "\n*** Indexing - Testing reference assignment with key ***\n"; $testvalues=array(null, 0, 1, true, false,0.1,array()); foreach ($testvalues as $testvalue) { - $testvalue['foo']=&$array; - var_dump ($testvalue); + try { + $testvalue['foo']=&$array; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump($testvalue); } echo "*** Indexing - Testing value assignment no key ***\n"; $array=array(1); $testvalues=array(null, 0, 1, true, false,0.1,array()); foreach ($testvalues as $testvalue) { - $testvalue[]=$array; - var_dump ($testvalue); + try { + $testvalue[]=$array; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump ($testvalue); } echo "\n*** Indexing - Testing reference assignment no key ***\n"; $testvalues=array(null, 0, 1, true, false,0.1,array()); foreach ($testvalues as $testvalue) { - $testvalue[]=&$array; - var_dump ($testvalue); + try { + $testvalue[]=&$array; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump ($testvalue); } @@ -47,14 +63,11 @@ array(1) { int(1) } } - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(0) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(1) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array bool(true) array(1) { ["foo"]=> @@ -66,15 +79,14 @@ array(1) { Warning: Illegal string offset 'foo' in %s on line %d -Notice: Array to string conversion in %s on line %d +Warning: Array to string conversion in %s on line %d string(1) "A" Warning: Illegal string offset 'foo' in %s on line %d -Notice: Array to string conversion in %s on line %d +Warning: Array to string conversion in %s on line %d string(1) "A" - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array float(0.1) array(1) { ["foo"]=> @@ -92,14 +104,11 @@ array(1) { int(1) } } - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(0) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(1) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array bool(true) array(1) { ["foo"]=> @@ -108,8 +117,7 @@ array(1) { int(1) } } - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array float(0.1) array(1) { ["foo"]=> @@ -126,14 +134,11 @@ array(1) { int(1) } } - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(0) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(1) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array bool(true) array(1) { [0]=> @@ -142,8 +147,7 @@ array(1) { int(1) } } - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array float(0.1) array(1) { [0]=> @@ -161,14 +165,11 @@ array(1) { int(1) } } - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(0) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array int(1) - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array bool(true) array(1) { [0]=> @@ -177,8 +178,7 @@ array(1) { int(1) } } - -Warning: Cannot use a scalar value as an array in %s on line %d +Cannot use a scalar value as an array float(0.1) array(1) { [0]=> diff --git a/Zend/tests/indirect_call_array_005.phpt b/Zend/tests/indirect_call_array_005.phpt index 4938856ed2..bd11df2d12 100644 --- a/Zend/tests/indirect_call_array_005.phpt +++ b/Zend/tests/indirect_call_array_005.phpt @@ -19,10 +19,7 @@ $callback = ['TestClass', 'method']; echo $callback(); ?> --EXPECTF-- -Deprecated: Non-static method TestClass::method() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d +Fatal error: Uncaught Error: Non-static method TestClass::method() cannot be called statically in %s:%d Stack trace: -#0 %s(%d): TestClass::method() -#1 {main} +#0 {main} thrown in %s on line %d diff --git a/Zend/tests/indirect_call_string_003.phpt b/Zend/tests/indirect_call_string_003.phpt index a6839df8a7..99289c4e1c 100644 --- a/Zend/tests/indirect_call_string_003.phpt +++ b/Zend/tests/indirect_call_string_003.phpt @@ -19,10 +19,7 @@ $callback = 'TestClass::method'; echo $callback(); ?> --EXPECTF-- -Deprecated: Non-static method TestClass::method() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d +Fatal error: Uncaught Error: Non-static method TestClass::method() cannot be called statically in %s:%d Stack trace: -#0 %s(%d): TestClass::method() -#1 {main} +#0 {main} thrown in %s on line %d diff --git a/Zend/tests/inference_infinite_loop.phpt b/Zend/tests/inference_infinite_loop.phpt index 1e94ea8040..ffa5cdbf89 100644 --- a/Zend/tests/inference_infinite_loop.phpt +++ b/Zend/tests/inference_infinite_loop.phpt @@ -14,4 +14,4 @@ test(); ?> --EXPECTF-- -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d diff --git a/Zend/tests/instanceof.phpt b/Zend/tests/instanceof.phpt index 97d67ff567..662185dcea 100644 --- a/Zend/tests/instanceof.phpt +++ b/Zend/tests/instanceof.phpt @@ -1,5 +1,5 @@ --TEST-- -instanceof shouldn't call __autoload +instanceof shouldn't call autoloader --FILE-- <?php spl_autoload_register(function ($name) { diff --git a/Zend/tests/instanceof_001.phpt b/Zend/tests/instanceof_001.phpt index 6bdcb896af..27170420f0 100644 --- a/Zend/tests/instanceof_001.phpt +++ b/Zend/tests/instanceof_001.phpt @@ -8,7 +8,7 @@ var_dump($a instanceof stdClass); var_dump(new stdCLass instanceof stdClass); -$b = create_function('', 'return new stdClass;'); +$b = function() { return new stdClass; }; var_dump($b() instanceof stdClass); $c = array(new stdClass); @@ -20,8 +20,6 @@ var_dump(@$inexistent instanceof stdClass); --EXPECTF-- bool(true) bool(true) - -Deprecated: Function create_function() is deprecated in %s on line %d bool(true) bool(true) bool(false) diff --git a/Zend/tests/interface_exists_001.phpt b/Zend/tests/interface_exists_001.phpt index ab20dd20ea..84e9c6df1e 100644 --- a/Zend/tests/interface_exists_001.phpt +++ b/Zend/tests/interface_exists_001.phpt @@ -9,13 +9,9 @@ interface foo { var_dump(interface_exists('foo')); var_dump(interface_exists(1)); var_dump(interface_exists(NULL)); -var_dump(interface_exists(new stdClass)); ?> ---EXPECTF-- +--EXPECT-- bool(true) bool(false) bool(false) - -Warning: interface_exists() expects parameter 1 to be string, object given in %s on line %d -NULL diff --git a/Zend/tests/is_a.phpt b/Zend/tests/is_a.phpt index 3714d50a62..f37c4638a8 100644 --- a/Zend/tests/is_a.phpt +++ b/Zend/tests/is_a.phpt @@ -1,5 +1,5 @@ --TEST-- -is_a() and is_subclass_of() shouldn't call __autoload +is_a() and is_subclass_of() shouldn't call autoloader --INI-- error_reporting=14335 --FILE-- diff --git a/Zend/tests/isset_003.phpt b/Zend/tests/isset_003.phpt index 06cbe3d51d..7b29c1e6b8 100644 --- a/Zend/tests/isset_003.phpt +++ b/Zend/tests/isset_003.phpt @@ -1,5 +1,5 @@ --TEST-- -Testing isset accessing undefined array itens and properties +Testing isset accessing undefined array items and properties --FILE-- <?php @@ -29,13 +29,13 @@ bool(true) bool(false) bool(false) -Notice: Undefined variable: c in %s on line %d +Warning: Undefined variable: c in %s on line %d -Notice: Undefined variable: d in %s on line %d +Warning: Undefined variable: d in %s on line %d -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d -Notice: Trying to get property '' of non-object in %s on line %d +Warning: Trying to get property '' of non-object in %s on line %d bool(false) bool(true) bool(false) diff --git a/Zend/tests/isset_array.phpt b/Zend/tests/isset_array.phpt new file mode 100644 index 0000000000..c7c1876410 --- /dev/null +++ b/Zend/tests/isset_array.phpt @@ -0,0 +1,48 @@ +--TEST-- +Using isset() with arrays +--FILE-- +<?php + +$array = [ + 0 => true, + "a" => true, +]; + +var_dump(isset($array[0])); + +var_dump(isset($array["a"])); + +var_dump(isset($array[false])); + +var_dump(isset($array[0.6])); + +var_dump(isset($array[true])); + +var_dump(isset($array[null])); + +var_dump(isset($array[STDIN])); + +try { + isset($array[[]]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + isset($array[new stdClass()]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) + +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +bool(false) +Illegal offset type in isset or empty +Illegal offset type in isset or empty diff --git a/Zend/tests/list_keyed_conversions.phpt b/Zend/tests/list_keyed_conversions.phpt index bf0349b327..1dd48de9f2 100644 --- a/Zend/tests/list_keyed_conversions.phpt +++ b/Zend/tests/list_keyed_conversions.phpt @@ -29,6 +29,6 @@ int(1) int(0) int(1) -Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d Notice: Undefined offset: 1 in %s on line %d diff --git a/Zend/tests/lsb_001.phpt b/Zend/tests/lsb_001.phpt index 075109259a..ca2739d102 100644 --- a/Zend/tests/lsb_001.phpt +++ b/Zend/tests/lsb_001.phpt @@ -47,7 +47,6 @@ echo ChildClass2::testStaticVar() . "\n"; echo ChildClass2::testClassConst() . "\n"; echo ChildClass2::testStaticFunction() . "\n"; ?> -==DONE== --EXPECT-- TestClassStatic TestClassConst @@ -58,4 +57,3 @@ ChildClassFunction TestClassStatic TestClassConst TestClassFunction -==DONE== diff --git a/Zend/tests/lsb_002.phpt b/Zend/tests/lsb_002.phpt index 1f433c3038..53eacc90ab 100644 --- a/Zend/tests/lsb_002.phpt +++ b/Zend/tests/lsb_002.phpt @@ -52,7 +52,6 @@ echo $childClass2->testStaticVar() . "\n"; echo $childClass2->testClassConst() . "\n"; echo $childClass2->testStaticFunction() . "\n"; ?> -==DONE== --EXPECT-- TestClassStatic TestClassConst @@ -63,4 +62,3 @@ ChildClassFunction TestClassStatic TestClassConst TestClassFunction -==DONE== diff --git a/Zend/tests/lsb_003.phpt b/Zend/tests/lsb_003.phpt index a7a787e568..aa10071b5f 100644 --- a/Zend/tests/lsb_003.phpt +++ b/Zend/tests/lsb_003.phpt @@ -17,8 +17,6 @@ $childClass = ChildClass::createInstance(); echo get_class($testClass) . "\n"; echo get_class($childClass) . "\n"; ?> -==DONE== --EXPECT-- TestClass ChildClass -==DONE== diff --git a/Zend/tests/lsb_004.phpt b/Zend/tests/lsb_004.phpt index 9583ef2547..3f26e339c3 100644 --- a/Zend/tests/lsb_004.phpt +++ b/Zend/tests/lsb_004.phpt @@ -14,8 +14,6 @@ class ChildClass extends TestClass {} echo TestClass::getClassName() . "\n"; echo ChildClass::getClassName() . "\n"; ?> -==DONE== --EXPECT-- TestClass ChildClass -==DONE== diff --git a/Zend/tests/lsb_005.phpt b/Zend/tests/lsb_005.phpt index a01ccd7ca9..b21d049549 100644 --- a/Zend/tests/lsb_005.phpt +++ b/Zend/tests/lsb_005.phpt @@ -35,7 +35,6 @@ class TestBB extends TestB { TestA::test(); ?> -==DONE== --EXPECT-- TestA TestB @@ -48,4 +47,3 @@ TestBB TestC TestBB TestA -==DONE== diff --git a/Zend/tests/lsb_015.phpt b/Zend/tests/lsb_015.phpt index 5c40c13160..10df17686b 100644 --- a/Zend/tests/lsb_015.phpt +++ b/Zend/tests/lsb_015.phpt @@ -67,7 +67,6 @@ A::myCatch(); echo "via B:\n"; B::myCatch(); ?> -==DONE== --EXPECT-- via A: A @@ -89,4 +88,3 @@ B B B B -==DONE== diff --git a/Zend/tests/lsb_016.phpt b/Zend/tests/lsb_016.phpt index 4c5fa3248e..b585a9fb6c 100644 --- a/Zend/tests/lsb_016.phpt +++ b/Zend/tests/lsb_016.phpt @@ -33,9 +33,7 @@ $o->test(); $o->a = "b"; echo $o->a; ?> -==DONE== --EXPECT-- TestChild TestChild TestChild -==DONE== diff --git a/Zend/tests/lsb_017.phpt b/Zend/tests/lsb_017.phpt index 5f5ca4351f..7f9e77b5f3 100644 --- a/Zend/tests/lsb_017.phpt +++ b/Zend/tests/lsb_017.phpt @@ -20,10 +20,8 @@ class D extends A { echo A::test(B::test(C::test(D::test())))."\n"; ?> -==DONE== --EXPECT-- D C B A -==DONE== diff --git a/Zend/tests/lsb_018.phpt b/Zend/tests/lsb_018.phpt index c7877cddf7..9511426d48 100644 --- a/Zend/tests/lsb_018.phpt +++ b/Zend/tests/lsb_018.phpt @@ -54,7 +54,6 @@ $x->identify(); $y->identify(); $z->identify(); ?> -===DONE=== --EXPECTF-- object(Foo)#%d (1) { ["instanceId":"Singleton":private]=> @@ -92,4 +91,3 @@ object(Baz)#%d (1) { ["instanceId":"Singleton":private]=> int(2) } -===DONE=== diff --git a/Zend/tests/method_argument_binding.phpt b/Zend/tests/method_argument_binding.phpt index dea12621a3..32acd93c63 100644 --- a/Zend/tests/method_argument_binding.phpt +++ b/Zend/tests/method_argument_binding.phpt @@ -43,4 +43,4 @@ class E extends D { --EXPECTF-- int(2) -Notice: Undefined variable: x in %s on line %d +Warning: Undefined variable: x in %s on line %d diff --git a/Zend/tests/methods-on-non-objects-call-user-func.phpt b/Zend/tests/methods-on-non-objects-call-user-func.phpt index 027aa64c20..63884abc79 100644 --- a/Zend/tests/methods-on-non-objects-call-user-func.phpt +++ b/Zend/tests/methods-on-non-objects-call-user-func.phpt @@ -2,11 +2,12 @@ call_user_func() in combination with "Call to a member function method() on a non-object" --FILE-- <?php -$comparator= null; -var_dump(call_user_func([$comparator, 'compare'], 1, 2)); -echo "Alive\n"; +$comparator = null; +try { + var_dump(call_user_func([$comparator, 'compare'], 1, 2)); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- -Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d -NULL -Alive +--EXPECT-- +call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object diff --git a/Zend/tests/multibyte/bug68665.phpt b/Zend/tests/multibyte/bug68665.phpt index 6846776570..e2c5a860f5 100644 --- a/Zend/tests/multibyte/bug68665.phpt +++ b/Zend/tests/multibyte/bug68665.phpt @@ -17,7 +17,5 @@ internal_encoding=big5 echo '\'hello'; ?> -===DONE=== --EXPECT-- 'hello -===DONE=== diff --git a/Zend/tests/multibyte/multibyte_encoding_001.phpt b/Zend/tests/multibyte/multibyte_encoding_001.phpt index 1a094814ec..9f3a748e78 100644 --- a/Zend/tests/multibyte/multibyte_encoding_001.phpt +++ b/Zend/tests/multibyte/multibyte_encoding_001.phpt @@ -18,7 +18,5 @@ declare(encoding='Shift_JIS'); $s = "•\"; // 0x95+0x5c in script, not somewhere else " printf("%x:%x\n", ord($s[0]), ord($s[1])); ?> -===DONE=== --EXPECT-- 95:5c -===DONE=== diff --git a/Zend/tests/multibyte/multibyte_encoding_002.phpt b/Zend/tests/multibyte/multibyte_encoding_002.phpt index 58ea015a6f..c4c225c8f7 100644 --- a/Zend/tests/multibyte/multibyte_encoding_002.phpt +++ b/Zend/tests/multibyte/multibyte_encoding_002.phpt @@ -16,7 +16,5 @@ internal_encoding=iso-8859-1 <?php print "Hello World\n"; ?> -===DONE=== --EXPECT-- Hello World -===DONE=== diff --git a/Zend/tests/nowdoc_015.phpt b/Zend/tests/nowdoc_015.phpt index 9eb83bd063..56de362dd5 100644 --- a/Zend/tests/nowdoc_015.phpt +++ b/Zend/tests/nowdoc_015.phpt @@ -2,7 +2,7 @@ Test nowdoc and line numbering --FILE-- <?php -function error_handler($num, $msg, $file, $line, $vars) { +function error_handler($num, $msg, $file, $line) { echo $line,"\n"; } set_error_handler('error_handler'); diff --git a/Zend/tests/ns_041.phpt b/Zend/tests/ns_041.phpt index bd9dfbd093..3a2fe7758b 100644 --- a/Zend/tests/ns_041.phpt +++ b/Zend/tests/ns_041.phpt @@ -17,5 +17,7 @@ ok ok ok -Warning: Use of undefined constant BAR - assumed 'BAR' (this will throw an Error in a future version of PHP) in %sns_041.php on line 9 -BAR +Fatal error: Uncaught Error: Undefined constant 'test\ns1\BAR' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/ns_069.phpt b/Zend/tests/ns_069.phpt index cbfb927049..19b6fe8c2b 100644 --- a/Zend/tests/ns_069.phpt +++ b/Zend/tests/ns_069.phpt @@ -16,9 +16,7 @@ class Test { Test::f(); ?> -===DONE=== --EXPECT-- string(3) "foo" string(0) "" string(3) "foo" -===DONE=== diff --git a/Zend/tests/ns_076.phpt b/Zend/tests/ns_076.phpt index ea97e924b1..0db8aeba62 100644 --- a/Zend/tests/ns_076.phpt +++ b/Zend/tests/ns_076.phpt @@ -3,26 +3,28 @@ --FILE-- <?php namespace foo; +use Error; -$a = array(unknown => unknown); - -echo unknown; -echo "\n"; -var_dump($a); -echo \unknown; ---EXPECTF-- -Warning: Use of undefined constant unknown - assumed 'unknown' (this will throw an Error in a future version of PHP) in %sns_076.php on line %d +try { + $a = array(unknown => unknown); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -Warning: Use of undefined constant unknown - assumed 'unknown' (this will throw an Error in a future version of PHP) in %sns_076.php on line %d +try { + echo unknown; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -Warning: Use of undefined constant unknown - assumed 'unknown' (this will throw an Error in a future version of PHP) in %sns_076.php on line %d -unknown -array(1) { - ["unknown"]=> - %s(7) "unknown" +try { + echo \unknown; +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -Fatal error: Uncaught Error: Undefined constant 'unknown' in %sns_076.php:%d -Stack trace: -#0 {main} - thrown in %sns_076.php on line %d +?> +--EXPECT-- +Undefined constant 'foo\unknown' +Undefined constant 'foo\unknown' +Undefined constant 'unknown' diff --git a/Zend/tests/object_types/invalid_default_value.phpt b/Zend/tests/object_types/invalid_default_value.phpt index 2768e00e7d..39272b05c0 100644 --- a/Zend/tests/object_types/invalid_default_value.phpt +++ b/Zend/tests/object_types/invalid_default_value.phpt @@ -7,4 +7,4 @@ function test(object $obj = 42) { } ?> --EXPECTF-- -Fatal error: Default value for parameters with an object type can only be NULL in %s on line %d +Fatal error: Cannot use int as default value for parameter $obj of type object in %s on line %d diff --git a/Zend/tests/objects_002.phpt b/Zend/tests/objects_002.phpt index 1c45b2230c..66cc09129f 100644 --- a/Zend/tests/objects_002.phpt +++ b/Zend/tests/objects_002.phpt @@ -17,8 +17,6 @@ class test3 extends test { function foo($arg) {} } -echo "Done\n"; ?> --EXPECTF-- -Warning: Declaration of test3::foo($arg) should be compatible with test::foo() in %s on line %d -Done +Fatal error: Declaration of test3::foo($arg) must be compatible with test::foo() in %s on line %d diff --git a/Zend/tests/objects_003.phpt b/Zend/tests/objects_003.phpt index 4486888c40..300cda0cd9 100644 --- a/Zend/tests/objects_003.phpt +++ b/Zend/tests/objects_003.phpt @@ -17,8 +17,6 @@ class test3 extends test { function foo($arg, $arg2) {} } -echo "Done\n"; ?> --EXPECTF-- -Warning: Declaration of test3::foo($arg, $arg2) should be compatible with test::foo($arg) in %s on line %d -Done +Fatal error: Declaration of test3::foo($arg, $arg2) must be compatible with test::foo($arg) in %s on line %d diff --git a/Zend/tests/objects_004.phpt b/Zend/tests/objects_004.phpt index 1cc90384a7..7c9ca452c8 100644 --- a/Zend/tests/objects_004.phpt +++ b/Zend/tests/objects_004.phpt @@ -17,8 +17,6 @@ class test3 extends test { function foo(&$arg) {} } -echo "Done\n"; ?> --EXPECTF-- -Warning: Declaration of test3::foo(&$arg) should be compatible with test::foo($arg) in %s on line %d -Done +Fatal error: Declaration of test3::foo(&$arg) must be compatible with test::foo($arg) in %s on line %d diff --git a/Zend/tests/objects_005.phpt b/Zend/tests/objects_005.phpt index a2369b731a..6007ccbbc9 100644 --- a/Zend/tests/objects_005.phpt +++ b/Zend/tests/objects_005.phpt @@ -17,8 +17,6 @@ class test3 extends test { function foo() {} } -echo "Done\n"; ?> --EXPECTF-- -Warning: Declaration of test3::foo() should be compatible with & test::foo() in %s on line %d -Done +Fatal error: Declaration of test3::foo() must be compatible with & test::foo() in %s on line %d diff --git a/Zend/tests/objects_006.phpt b/Zend/tests/objects_006.phpt index ed6ea6047a..e520342180 100644 --- a/Zend/tests/objects_006.phpt +++ b/Zend/tests/objects_006.phpt @@ -17,8 +17,6 @@ class test3 extends test { function foo($arg, $arg2) {} } -echo "Done\n"; ?> --EXPECTF-- -Warning: Declaration of test3::foo($arg, $arg2) should be compatible with test::foo($arg, $arg2 = NULL) in %s on line %d -Done +Fatal error: Declaration of test3::foo($arg, $arg2) must be compatible with test::foo($arg, $arg2 = NULL) in %s on line %d diff --git a/Zend/tests/objects_007.phpt b/Zend/tests/objects_007.phpt index 3094d60e8e..2df30b9068 100644 --- a/Zend/tests/objects_007.phpt +++ b/Zend/tests/objects_007.phpt @@ -17,8 +17,6 @@ class test3 extends test { function foo($arg, &$arg2) {} } -echo "Done\n"; ?> --EXPECTF-- -Warning: Declaration of test3::foo($arg, &$arg2) should be compatible with test::foo($arg, &$arg2 = NULL) in %s on line %d -Done +Fatal error: Declaration of test3::foo($arg, &$arg2) must be compatible with test::foo($arg, &$arg2 = NULL) in %s on line %d diff --git a/Zend/tests/objects_008.phpt b/Zend/tests/objects_008.phpt index 6554be99eb..b563061051 100644 --- a/Zend/tests/objects_008.phpt +++ b/Zend/tests/objects_008.phpt @@ -17,8 +17,6 @@ class test3 extends test { function foo(Test3 $arg) {} } -echo "Done\n"; ?> --EXPECTF-- -Warning: Declaration of test3::foo(Test3 $arg) should be compatible with test::foo(Test $arg) in %s on line %d -Done +Fatal error: Declaration of test3::foo(Test3 $arg) must be compatible with test::foo(Test $arg) in %s on line %d diff --git a/Zend/tests/objects_015.phpt b/Zend/tests/objects_015.phpt index 714d27ad5b..e0f5e9a93d 100644 --- a/Zend/tests/objects_015.phpt +++ b/Zend/tests/objects_015.phpt @@ -14,7 +14,6 @@ var_dump($o != null); var_dump(is_null($o)); ?> -===DONE=== --EXPECT-- bool(false) bool(true) @@ -23,4 +22,3 @@ bool(true) bool(false) bool(true) bool(false) -===DONE=== diff --git a/Zend/tests/objects_020.phpt b/Zend/tests/objects_020.phpt deleted file mode 100644 index 4b0e0d1ec7..0000000000 --- a/Zend/tests/objects_020.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Accessing members of standard object through of variable variable ---FILE-- -<?php - -error_reporting(E_ALL); - -$test = 'stdclass'; - -$$test->a =& $$test; -$$test->a->b[] = 2; - -var_dump($$test); - -?> ---EXPECTF-- -Warning: Creating default object from empty value in %sobjects_020.php on line 7 -object(stdClass)#%d (2) { - ["a"]=> - *RECURSION* - ["b"]=> - array(1) { - [0]=> - int(2) - } -} diff --git a/Zend/tests/objects_027.phpt b/Zend/tests/objects_027.phpt index 6ee7d5a491..b579278f2e 100644 --- a/Zend/tests/objects_027.phpt +++ b/Zend/tests/objects_027.phpt @@ -17,26 +17,12 @@ class foo extends bar { $foo = new foo; $foo->test(); -$foo::test(); call_user_func(array($foo, 'test')); -call_user_func(array('foo', 'test')); ?> --EXPECTF-- object(foo)#%d (0) { } - -Deprecated: Non-static method foo::test() should not be called statically in %s on line %d - -Deprecated: Non-static method bar::show() should not be called statically in %s on line %d -object(foo)#%d (0) { -} -object(foo)#%d (0) { -} - -Deprecated: %son-static method foo::test() should not be called statically in %s on line %d - -Deprecated: Non-static method bar::show() should not be called statically in %s on line %d object(foo)#%d (0) { } diff --git a/Zend/tests/objects_032.phpt b/Zend/tests/objects_032.phpt index 52a5e9fed9..b4312ac3f8 100644 --- a/Zend/tests/objects_032.phpt +++ b/Zend/tests/objects_032.phpt @@ -25,7 +25,6 @@ $a['foo']['bar'] = 2; var_dump($a); ?> -==DONE== --EXPECT-- object(A)#1 (1) { ["foo"]=> @@ -37,4 +36,3 @@ object(A)#1 (1) { } } } -==DONE== diff --git a/Zend/tests/offset_array.phpt b/Zend/tests/offset_array.phpt index a1d0a43c69..97b6a06b1c 100644 --- a/Zend/tests/offset_array.phpt +++ b/Zend/tests/offset_array.phpt @@ -17,10 +17,18 @@ $fp = fopen(__FILE__, "r"); var_dump($arr[$fp]); $obj = new stdClass; -var_dump($arr[$obj]); +try { + var_dump($arr[$obj]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} $arr1 = Array(1,2,3); -var_dump($arr[$arr1]); +try { + var_dump($arr[$arr1]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} echo "Done\n"; ?> @@ -36,12 +44,8 @@ NULL int(2) int(1) -Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d int(%d) - -Warning: Illegal offset type in %s on line %d -NULL - -Warning: Illegal offset type in %s on line %d -NULL +Illegal offset type +Illegal offset type Done diff --git a/Zend/tests/offset_bool.phpt b/Zend/tests/offset_bool.phpt index 8ed9f28e43..ae8df6d2b5 100644 --- a/Zend/tests/offset_bool.phpt +++ b/Zend/tests/offset_bool.phpt @@ -25,30 +25,30 @@ var_dump($bool[$arr]); echo "Done\n"; ?> --EXPECTF-- -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL -Notice: Trying to access array offset on value of type bool in %s on line %d +Warning: Trying to access array offset on value of type bool in %s on line %d NULL Done diff --git a/Zend/tests/offset_long.phpt b/Zend/tests/offset_long.phpt index 4c6b3972d2..17dfe0d29b 100644 --- a/Zend/tests/offset_long.phpt +++ b/Zend/tests/offset_long.phpt @@ -25,30 +25,30 @@ var_dump($long[$arr]); echo "Done\n"; ?> --EXPECTF-- -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL -Notice: Trying to access array offset on value of type int in %s on line %d +Warning: Trying to access array offset on value of type int in %s on line %d NULL Done diff --git a/Zend/tests/offset_null.phpt b/Zend/tests/offset_null.phpt index ad0b1f3049..ae02eece77 100644 --- a/Zend/tests/offset_null.phpt +++ b/Zend/tests/offset_null.phpt @@ -25,30 +25,30 @@ var_dump($null[$arr]); echo "Done\n"; ?> --EXPECTF-- -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL -Notice: Trying to access array offset on value of type null in %s on line %d +Warning: Trying to access array offset on value of type null in %s on line %d NULL Done diff --git a/Zend/tests/offset_string.phpt b/Zend/tests/offset_string.phpt index 3ad48e7412..1a9667cb8f 100644 --- a/Zend/tests/offset_string.phpt +++ b/Zend/tests/offset_string.phpt @@ -17,23 +17,35 @@ var_dump($str[TRUE]); var_dump($str[FALSE]); $fp = fopen(__FILE__, "r"); -var_dump($str[$fp]); +try { + var_dump($str[$fp]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} $obj = new stdClass; -var_dump($str[$obj]); +try { + var_dump($str[$obj]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} $arr = Array(1,2,3); -var_dump($str[$arr]); +try { + var_dump($str[$arr]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} echo "Done\n"; ?> --EXPECTF-- string(1) "i" -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d string(1) "S" -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d string(1) "S" Warning: Illegal string offset 'run away' in %s on line %d @@ -46,20 +58,14 @@ string(1) "o" Notice: A non well formed numeric value encountered in %s on line %d string(1) "r" -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d string(1) "i" -Notice: String offset cast occurred in %s on line %d +Warning: String offset cast occurred in %s on line %d string(1) "S" - -Warning: Illegal offset type in %s on line %d -string(1) "%s" - -Warning: Illegal offset type in %s on line %d +Illegal offset type Notice: Object of class stdClass could not be converted to int in %s on line %d -string(1) "%s" - -Warning: Illegal offset type in %s on line %d -string(1) "i" +Illegal offset type +Illegal offset type Done diff --git a/Zend/tests/overloaded_func_001.phpt b/Zend/tests/overloaded_func_001.phpt index 31585d505a..7fc435f920 100644 --- a/Zend/tests/overloaded_func_001.phpt +++ b/Zend/tests/overloaded_func_001.phpt @@ -6,10 +6,10 @@ if (!extension_loaded('zend-test')) die('skip zend-test extension not loaded'); ?> --FILE-- <?php +$o = new _ZendTestChildClass(); +var_dump($o->test()); var_dump(_ZendTestClass::test()); ?> ---EXPECTF-- -Fatal error: Uncaught Error: Cannot call overloaded function for non-object in %soverloaded_func_001.php:%d -Stack trace: -#0 {main} - thrown in %soverloaded_func_001.php on line %d +--EXPECT-- +string(4) "test" +string(4) "test" diff --git a/Zend/tests/parse_str_with_unpack.phpt b/Zend/tests/parse_str_with_unpack.phpt deleted file mode 100644 index 8daa711374..0000000000 --- a/Zend/tests/parse_str_with_unpack.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Calling parse_str through argument unpacking ---FILE-- -<?php - -function test() { - $i = 0; - parse_str(...["i=41"]); - var_dump($i + 1); -} -test(); - -?> ---EXPECTF-- -Deprecated: parse_str(): Calling parse_str() without the result argument is deprecated in %s on line %d -int(42) diff --git a/Zend/tests/php_errormsg_misoptimization.phpt b/Zend/tests/php_errormsg_misoptimization.phpt deleted file mode 100644 index ae389db248..0000000000 --- a/Zend/tests/php_errormsg_misoptimization.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -The variable $php_errormsg shouldn't be optimized as it may be unpredictably modified ---INI-- -track_errors=1 ---FILE-- -<?php - -function test() { - $php_errormsg = 1; - echo $undef; - var_dump($php_errormsg + 1); -} -test(); - -?> ---EXPECTF-- -Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0 - -Notice: Undefined variable: undef in %s on line %d - -Warning: A non-numeric value encountered in %s on line %d -int(1) diff --git a/Zend/tests/pow_array_leak.phpt b/Zend/tests/pow_array_leak.phpt index e9165bbbc5..a17a290458 100644 --- a/Zend/tests/pow_array_leak.phpt +++ b/Zend/tests/pow_array_leak.phpt @@ -4,14 +4,30 @@ Memory leak on ** with result==op1 array <?php $x = [0]; -$x **= 1; +try { + $x **= 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($x); $x = [0]; -$x **= $x; +try { + $x **= $x; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} var_dump($x); ?> --EXPECT-- -int(0) -int(0) +Unsupported operand types +array(1) { + [0]=> + int(0) +} +Unsupported operand types +array(1) { + [0]=> + int(0) +} diff --git a/Zend/tests/result_unused.phpt b/Zend/tests/result_unused.phpt index 12892e8415..263755beb0 100644 --- a/Zend/tests/result_unused.phpt +++ b/Zend/tests/result_unused.phpt @@ -24,5 +24,5 @@ $x->prop; $x->y; echo "ok\n"; --EXPECTF-- -Notice: Uninitialized string offset: 3 in %sresult_unused.php on line %d +Warning: Uninitialized string offset: 3 in %s on line %d ok diff --git a/Zend/tests/return_types/023.phpt b/Zend/tests/return_types/023.phpt deleted file mode 100644 index e8e8732ef1..0000000000 --- a/Zend/tests/return_types/023.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -PHP 4 Constructors cannot declare a return type ---FILE-- -<?php - -class Foo { - function foo() : Foo {} -} ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; Foo has a deprecated constructor in %s on line %d - -Fatal error: Constructor %s::%s() cannot declare a return type in %s on line %d diff --git a/Zend/tests/return_types/bug71978.phpt b/Zend/tests/return_types/bug71978.phpt index e3c8440212..cfe8905dec 100644 --- a/Zend/tests/return_types/bug71978.phpt +++ b/Zend/tests/return_types/bug71978.phpt @@ -2,12 +2,6 @@ Bug #71978 (Existence of return type hint affects other compatibility rules) --FILE-- <?php -class A { - function foo(int $a) {} -} -class B extends A { - function foo(string $a) {} -} class A1 { function foo(int $a): int {} } @@ -16,6 +10,4 @@ class B1 extends A1 { } ?> --EXPECTF-- -Warning: Declaration of B::foo(string $a) should be compatible with A::foo(int $a) in %s on line %d - -Warning: Declaration of B1::foo(string $a): int should be compatible with A1::foo(int $a): int in %s on line %d +Fatal error: Declaration of B1::foo(string $a): int must be compatible with A1::foo(int $a): int in %s on line %d diff --git a/Zend/tests/return_types/generators002.phpt b/Zend/tests/return_types/generators002.phpt index 90bada714b..2e42f4b052 100644 --- a/Zend/tests/return_types/generators002.phpt +++ b/Zend/tests/return_types/generators002.phpt @@ -6,4 +6,4 @@ function test1() : StdClass { yield 1; } --EXPECTF-- -Fatal error: Generators may only declare a return type of Generator, Iterator, Traversable, or iterable, StdClass is not permitted in %s on line %d +Fatal error: Generators may only declare a return type containing Generator, Iterator, Traversable, or iterable, StdClass is not permitted in %s on line %d diff --git a/Zend/tests/runtime_compile_time_binary_operands.phpt b/Zend/tests/runtime_compile_time_binary_operands.phpt index afced7af0c..2908bc3db1 100644 --- a/Zend/tests/runtime_compile_time_binary_operands.phpt +++ b/Zend/tests/runtime_compile_time_binary_operands.phpt @@ -148,7 +148,6 @@ if($c === 0) { echo "Failed: $f\n"; } ?> -===DONE=== --CLEAN-- <?php $fl = __DIR__ . DIRECTORY_SEPARATOR . 'compare_binary_operands_temp.php'; @@ -156,4 +155,3 @@ $fl = __DIR__ . DIRECTORY_SEPARATOR . 'compare_binary_operands_temp.php'; ?> --EXPECT-- Failed: 0 -===DONE=== diff --git a/Zend/tests/settype_resource.phpt b/Zend/tests/settype_resource.phpt Binary files differindex a6721cb757..1b038613f3 100644 --- a/Zend/tests/settype_resource.phpt +++ b/Zend/tests/settype_resource.phpt diff --git a/Zend/tests/settype_string.phpt b/Zend/tests/settype_string.phpt Binary files differindex 3a2d59ecae..0c97450051 100644 --- a/Zend/tests/settype_string.phpt +++ b/Zend/tests/settype_string.phpt diff --git a/Zend/tests/str_offset_001.phpt b/Zend/tests/str_offset_001.phpt index 3317674857..04fadd3023 100644 --- a/Zend/tests/str_offset_001.phpt +++ b/Zend/tests/str_offset_001.phpt @@ -28,19 +28,19 @@ string(1) "a" string(1) "b" string(1) "c" -Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d +Warning: Uninitialized string offset: 3 in %s on line %d string(0) "" string(1) "b" -Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d +Warning: Uninitialized string offset: 1 in %s on line %d string(0) "" string(1) "a" string(1) "b" string(1) "c" -Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d +Warning: Uninitialized string offset: 3 in %s on line %d string(0) "" string(1) "b" -Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d +Warning: Uninitialized string offset: 1 in %s on line %d string(0) "" diff --git a/Zend/tests/str_offset_003.phpt b/Zend/tests/str_offset_003.phpt index e357ac0c01..4101ce522a 100644 --- a/Zend/tests/str_offset_003.phpt +++ b/Zend/tests/str_offset_003.phpt @@ -20,18 +20,18 @@ foo($str[2][-2]); foo($str[2][-1]); ?> --EXPECTF-- -Notice: Uninitialized string offset: -10 in %sstr_offset_003.php on line %d +Warning: Uninitialized string offset: -10 in %s on line %d string(0) "" string(1) "d" -Notice: Uninitialized string offset: -2 in %sstr_offset_003.php on line %d +Warning: Uninitialized string offset: -2 in %s on line %d string(0) "" string(1) "c" -Notice: Uninitialized string offset: -10 in %sstr_offset_003.php on line %d +Warning: Uninitialized string offset: -10 in %s on line %d string(0) "" string(1) "d" -Notice: Uninitialized string offset: -2 in %sstr_offset_003.php on line %d +Warning: Uninitialized string offset: -2 in %s on line %d string(0) "" string(1) "c" diff --git a/Zend/tests/strict_001.phpt b/Zend/tests/strict_001.phpt index 3fcaa8c2bc..54c5a76c48 100644 --- a/Zend/tests/strict_001.phpt +++ b/Zend/tests/strict_001.phpt @@ -14,6 +14,6 @@ var_dump($array[$fp]); echo "Done\n"; ?> --EXPECTF-- -Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d int(%d) Done diff --git a/Zend/tests/this_in_extract.phpt b/Zend/tests/this_in_extract.phpt index 9903d7d794..ef0a25a279 100644 --- a/Zend/tests/this_in_extract.phpt +++ b/Zend/tests/this_in_extract.phpt @@ -15,5 +15,5 @@ foo(); --EXPECTF-- Cannot re-assign $this -Notice: Undefined variable: a in %s on line %d +Warning: Undefined variable: a in %s on line %d NULL diff --git a/Zend/tests/this_in_mb_parse_str.phpt b/Zend/tests/this_in_mb_parse_str.phpt deleted file mode 100644 index 2d5af4794e..0000000000 --- a/Zend/tests/this_in_mb_parse_str.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -$this re-assign in mb_parse_str() ---SKIPIF-- -<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?> ---FILE-- -<?php -function foo() { - mb_parse_str("this=42"); - var_dump($this); -} -foo(); -?> ---EXPECTF-- -Deprecated: mb_parse_str(): Calling mb_parse_str() without the result argument is deprecated in %s on line %d - -Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_in_mb_parse_str.php:3 -Stack trace: -#0 %sthis_in_mb_parse_str.php(3): mb_parse_str('this=42') -#1 %sthis_in_mb_parse_str.php(6): foo() -#2 {main} - thrown in %sthis_in_mb_parse_str.php on line 3 diff --git a/Zend/tests/this_in_parse_str.phpt b/Zend/tests/this_in_parse_str.phpt deleted file mode 100644 index 0bd9064d60..0000000000 --- a/Zend/tests/this_in_parse_str.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -$this re-assign in parse_str() ---FILE-- -<?php -function foo() { - parse_str("this=42"); - var_dump($this); -} -foo(); -?> ---EXPECTF-- -Deprecated: parse_str(): Calling parse_str() without the result argument is deprecated in %s on line %d - -Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_in_parse_str.php:3 -Stack trace: -#0 %sthis_in_parse_str.php(3): parse_str('this=42') -#1 %sthis_in_parse_str.php(6): foo() -#2 {main} - thrown in %sthis_in_parse_str.php on line 3 diff --git a/Zend/tests/trait_exists_001.phpt b/Zend/tests/trait_exists_001.phpt index 10ce3fa0cb..8a7c55d586 100644 --- a/Zend/tests/trait_exists_001.phpt +++ b/Zend/tests/trait_exists_001.phpt @@ -9,13 +9,9 @@ trait foo { var_dump(trait_exists('foo')); var_dump(trait_exists(1)); var_dump(trait_exists(NULL)); -var_dump(trait_exists(new stdClass)); ?> ---EXPECTF-- +--EXPECT-- bool(true) bool(false) bool(false) - -Warning: trait_exists() expects parameter 1 to be string, object given in %s on line %d -NULL diff --git a/Zend/tests/traits/bug55554a.phpt b/Zend/tests/traits/bug55554a.phpt deleted file mode 100644 index dd844ba661..0000000000 --- a/Zend/tests/traits/bug55554a.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// All constructors should be registered as such - -trait TConstructor { - public function constructor() { - echo "ctor executed\n"; - } -} - -class NewConstructor { - use TConstructor { - constructor as __construct; - } -} - -class LegacyConstructor { - use TConstructor { - constructor as LegacyConstructor; - } -} - -echo "New constructor: "; -$o = new NewConstructor; - -echo "Legacy constructor: "; -$o = new LegacyConstructor; ---EXPECT-- -New constructor: ctor executed -Legacy constructor: ctor executed diff --git a/Zend/tests/traits/bug55554b.phpt b/Zend/tests/traits/bug55554b.phpt deleted file mode 100644 index 65ecb7adaf..0000000000 --- a/Zend/tests/traits/bug55554b.phpt +++ /dev/null @@ -1,55 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -trait TConstructor { - public function foo() { - echo "foo executed\n"; - } - public function bar() { - echo "bar executed\n"; - } -} - -class OverridingIsSilent1 { - use TConstructor { - foo as __construct; - } - - public function __construct() { - echo "OverridingIsSilent1 __construct\n"; - } -} - -$o = new OverridingIsSilent1; - -class OverridingIsSilent2 { - use TConstructor { - foo as OverridingIsSilent2; - } - - public function OverridingIsSilent2() { - echo "OverridingIsSilent2 OverridingIsSilent2\n"; - } -} - -$o = new OverridingIsSilent2; - -class ReportCollision { - use TConstructor { - bar as ReportCollision; - foo as __construct; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -OverridingIsSilent1 __construct - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; OverridingIsSilent2 has a deprecated constructor in %s on line %d -OverridingIsSilent2 OverridingIsSilent2 - -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/bug55554c.phpt b/Zend/tests/traits/bug55554c.phpt deleted file mode 100644 index 420689259e..0000000000 --- a/Zend/tests/traits/bug55554c.phpt +++ /dev/null @@ -1,44 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Test that the behavior is consistent with the existing handling of new -// and legacy constructors. -// Here, the traits conflicts are overridden by local definitions, -// and the two constructor definitions do not directly collide in that case. - -trait TC1 { - public function __construct() { - echo "TC1 executed\n"; - } - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -trait TC2 { - public function __construct() { - echo "TC2 executed\n"; - } - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -class ReportCollision { - use TC1, TC2; - - public function __construct() { - echo "New constructor executed\n"; - } - public function ReportCollision() { - echo "Legacy constructor executed\n"; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECT-- -ReportCollision: New constructor executed diff --git a/Zend/tests/traits/bug55554d.phpt b/Zend/tests/traits/bug55554d.phpt deleted file mode 100644 index 88564a83c1..0000000000 --- a/Zend/tests/traits/bug55554d.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Test mixed constructors from different traits, we are more strict about -// these cases, since that can lead to un-expected behavior. -// It is not consistent with the normal constructor handling, but -// here we have a chance to be more strict for the new traits. - -trait TNew { - public function __construct() { - echo "TNew executed\n"; - } -} - -trait TLegacy { - public function ReportCollision() { - echo "ReportCollision executed\n"; - } -} - -class ReportCollision { - use TNew, TLegacy; -} - -$o = new ReportCollision; ---EXPECTF-- -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/bug55554e.phpt b/Zend/tests/traits/bug55554e.phpt deleted file mode 100644 index ed1c324831..0000000000 --- a/Zend/tests/traits/bug55554e.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Ensuring that the collision still occurs as expected. - -trait TC1 { - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -trait TC2 { - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -class ReportCollision { - use TC1, TC2; -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -Fatal error: Trait method ReportCollision has not been applied, because there are collisions with other trait methods on ReportCollision in %s on line %d diff --git a/Zend/tests/traits/bug55554f.phpt b/Zend/tests/traits/bug55554f.phpt deleted file mode 100644 index d7d4fc007d..0000000000 --- a/Zend/tests/traits/bug55554f.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Ensuring that inconsistent constructor use results in an error to avoid -// problems creeping in. - -trait TNew { - public function __construct() { - echo "TNew executed\n"; - } -} - -class ReportCollision { - use TNew; - - public function ReportCollision() { - echo "ReportCollision executed\n"; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/bug55554g.phpt b/Zend/tests/traits/bug55554g.phpt deleted file mode 100644 index d7de8216b0..0000000000 --- a/Zend/tests/traits/bug55554g.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Ensuring that inconsistent constructor use results in an error to avoid -// problems creeping in. - -trait TLegacy { - public function ReportCollision() { - echo "TLegacy executed\n"; - } -} - -class ReportCollision { - use TLegacy; - - public function __construct() { - echo "ReportCollision executed\n"; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/noctor001.phpt b/Zend/tests/traits/noctor001.phpt deleted file mode 100644 index 19fe8dbd0d..0000000000 --- a/Zend/tests/traits/noctor001.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Don't mark trait methods as constructor ---FILE-- -<?php -trait Foo { - public function Foo() { - } -} - -class Bar { - use Foo; - public function Bar() { - } -} - -$rfoofoo = new ReflectionMethod('Foo::Foo'); -var_dump($rfoofoo->isConstructor()); - -$rbarfoo = new ReflectionMethod('Bar::Foo'); -var_dump($rbarfoo->isConstructor()); - -$rbarbar = new ReflectionMethod('Bar::Bar'); -var_dump($rbarbar->isConstructor()); -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; Bar has a deprecated constructor in %s on line %d -bool(false) -bool(false) -bool(true) diff --git a/Zend/tests/try/bug70228_7.phpt b/Zend/tests/try/bug70228_7.phpt index 4b8a80351c..531708f86a 100644 --- a/Zend/tests/try/bug70228_7.phpt +++ b/Zend/tests/try/bug70228_7.phpt @@ -21,9 +21,7 @@ function foo() { foo(); ?> -===DONE=== --EXPECT-- int(1) int(2) int(3) -===DONE=== diff --git a/Zend/tests/try/bug70228_8.phpt b/Zend/tests/try/bug70228_8.phpt index ad13113c71..93fc09f6a8 100644 --- a/Zend/tests/try/bug70228_8.phpt +++ b/Zend/tests/try/bug70228_8.phpt @@ -22,9 +22,7 @@ function foo() { foo(); ?> -===DONE=== --EXPECT-- int(1) int(2) int(3) -===DONE=== diff --git a/Zend/tests/try/catch_002.phpt b/Zend/tests/try/catch_002.phpt index 11d736abe2..11dbccf7df 100644 --- a/Zend/tests/try/catch_002.phpt +++ b/Zend/tests/try/catch_002.phpt @@ -27,7 +27,5 @@ catch(Exception $e) } ?> -===DONE=== --EXPECT-- Caught -===DONE=== diff --git a/Zend/tests/try/catch_003.phpt b/Zend/tests/try/catch_003.phpt index 414d50f815..579011f867 100644 --- a/Zend/tests/try/catch_003.phpt +++ b/Zend/tests/try/catch_003.phpt @@ -32,7 +32,5 @@ catch(Exception $e) } ?> -===DONE=== --EXPECT-- Caught -===DONE=== diff --git a/Zend/tests/try/catch_004.phpt b/Zend/tests/try/catch_004.phpt index 7c269cc336..5ec82998f7 100644 --- a/Zend/tests/try/catch_004.phpt +++ b/Zend/tests/try/catch_004.phpt @@ -37,7 +37,5 @@ class MyObject MyObject::test(); ?> -===DONE=== --EXPECT-- Caught -===DONE=== diff --git a/Zend/tests/try/try_finally_013.phpt b/Zend/tests/try/try_finally_013.phpt index a37df5147d..0e82dcbb4c 100644 --- a/Zend/tests/try/try_finally_013.phpt +++ b/Zend/tests/try/try_finally_013.phpt @@ -18,8 +18,6 @@ function foo() { foo(); ?> -===DONE=== --EXPECT-- try finally -===DONE=== diff --git a/Zend/tests/try/try_finally_014.phpt b/Zend/tests/try/try_finally_014.phpt index 284892a8b5..a45f63f1f3 100644 --- a/Zend/tests/try/try_finally_014.phpt +++ b/Zend/tests/try/try_finally_014.phpt @@ -20,8 +20,6 @@ function foo() { foo(); ?> -===DONE=== --EXPECT-- try finally -===DONE=== diff --git a/Zend/tests/try/try_finally_015.phpt b/Zend/tests/try/try_finally_015.phpt index d2580a2e33..f706b9c942 100644 --- a/Zend/tests/try/try_finally_015.phpt +++ b/Zend/tests/try/try_finally_015.phpt @@ -21,9 +21,7 @@ function foo() { foo(); ?> -===DONE=== --EXPECT-- int(1) int(2) int(3) -===DONE=== diff --git a/Zend/tests/try/try_finally_016.phpt b/Zend/tests/try/try_finally_016.phpt index dc91b42b50..f78a2914af 100644 --- a/Zend/tests/try/try_finally_016.phpt +++ b/Zend/tests/try/try_finally_016.phpt @@ -32,8 +32,6 @@ try { echo "outer catch\n"; } ?> -===DONE=== --EXPECT-- finally outer catch -===DONE=== diff --git a/Zend/tests/try/try_finally_017.phpt b/Zend/tests/try/try_finally_017.phpt index 5ba58afdea..b23840c611 100644 --- a/Zend/tests/try/try_finally_017.phpt +++ b/Zend/tests/try/try_finally_017.phpt @@ -34,9 +34,7 @@ function foo() { foo(); ?> -===DONE=== --EXPECT-- finally1 catch2 finally2 -===DONE=== diff --git a/Zend/tests/type_declarations/callable_001.phpt b/Zend/tests/type_declarations/callable_001.phpt index 3113bedcf0..d93e70923a 100644 --- a/Zend/tests/type_declarations/callable_001.phpt +++ b/Zend/tests/type_declarations/callable_001.phpt @@ -14,19 +14,13 @@ $closure = function () {}; foo("strpos"); foo("foo"); -foo(array("bar", "baz")); -foo(array("bar", "foo")); foo($closure); +foo(array("bar", "foo")); +foo(array("bar", "baz")); --EXPECTF-- string(6) "strpos" string(3) "foo" - -Deprecated: Non-static method bar::baz() should not be called statically in %s on line %d -array(2) { - [0]=> - string(3) "bar" - [1]=> - string(3) "baz" +object(Closure)#1 (0) { } array(2) { [0]=> @@ -34,5 +28,9 @@ array(2) { [1]=> string(3) "foo" } -object(Closure)#%d (0) { -} + +Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be callable, array given, called in %s on line %d and defined in %s:%d +Stack trace: +#0 %s(%d): foo(Array) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/confusable_type_warning.phpt b/Zend/tests/type_declarations/confusable_type_warning.phpt new file mode 100644 index 0000000000..e0202cee06 --- /dev/null +++ b/Zend/tests/type_declarations/confusable_type_warning.phpt @@ -0,0 +1,46 @@ +--TEST-- +Warnings for confusable types +--FILE-- +<?php + +function test1(integer $x) {} +function test2(double $x) {} +function test3(boolean $x) {} +function test4(resource $x) {} + +namespace Foo { + use integer as foo; + + function test5(\integer $x) {} + function test6(namespace\integer $x) {} + function test7(foo $x) {} + function test8(boolean $x) {} +} + +namespace Foo { + use integer; + function test9(integer $x) {} +} + +namespace { + use integer as foo; + + function test10(\integer $x) {} + function test11(namespace\integer $x) {} + function test12(foo $x) {} + function test13(boolean $x) {} +} + +?> +--EXPECTF-- +Warning: "integer" will be interpreted as a class name. Did you mean "int"? Write "\integer" to suppress this warning in %s on line %d + +Warning: "double" will be interpreted as a class name. Did you mean "float"? Write "\double" to suppress this warning in %s on line %d + +Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in %s on line %d + +Warning: "resource" is not a supported builtin type and will be interpreted as a class name. Write "\resource" to suppress this warning in %s on line %d + +Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\Foo\boolean" or import the class with "use" to suppress this warning in %s on line %d + +Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in %s on line %d diff --git a/Zend/tests/type_declarations/iterable_002.phpt b/Zend/tests/type_declarations/iterable_002.phpt index b9e02e40cd..fdc3b20df5 100644 --- a/Zend/tests/type_declarations/iterable_002.phpt +++ b/Zend/tests/type_declarations/iterable_002.phpt @@ -17,4 +17,4 @@ function baz(iterable $iterable = 1) { ?> --EXPECTF-- -Fatal error: Default value for parameters with iterable type can only be an array or NULL in %s on line %d +Fatal error: Cannot use int as default value for parameter $iterable of type iterable in %s on line %d diff --git a/Zend/tests/type_declarations/iterable_004.phpt b/Zend/tests/type_declarations/iterable_004.phpt index 58b3f67f40..fe9d4461b9 100644 --- a/Zend/tests/type_declarations/iterable_004.phpt +++ b/Zend/tests/type_declarations/iterable_004.phpt @@ -21,4 +21,4 @@ class Bar extends Foo { ?> --EXPECTF-- -Warning: Declaration of Bar::testScalar(iterable $iterable) should be compatible with Foo::testScalar(int $int) in %s on line %d +Fatal error: Declaration of Bar::testScalar(iterable $iterable) must be compatible with Foo::testScalar(int $int) in %s on line %d diff --git a/Zend/tests/type_declarations/nullable_void.phpt b/Zend/tests/type_declarations/nullable_void.phpt index 4ff0edb0d8..725c11bb59 100644 --- a/Zend/tests/type_declarations/nullable_void.phpt +++ b/Zend/tests/type_declarations/nullable_void.phpt @@ -8,4 +8,4 @@ function test() : ?void { ?> --EXPECTF-- -Fatal error: Void type cannot be nullable in %s on line %d +Fatal error: Void can only be used as a standalone type in %s on line %d diff --git a/Zend/tests/type_declarations/parameter_type_variance.phpt b/Zend/tests/type_declarations/parameter_type_variance.phpt index 61915a2e6c..e4e5400957 100644 --- a/Zend/tests/type_declarations/parameter_type_variance.phpt +++ b/Zend/tests/type_declarations/parameter_type_variance.phpt @@ -1,5 +1,5 @@ --TEST-- -Parameter variance with no type +Parameter variance with no type (class) --FILE-- <?php @@ -8,11 +8,6 @@ class Foo { function testBothClass(Foo $foo) {} function testChildClass($foo) {} function testNoneClass($foo) {} - - function testParentBuiltin(int $foo) {} - function testBothBuiltin(int $foo) {} - function testChildBuiltin($foo) {} - function testNoneBuiltin($foo) {} } class Bar extends Foo { @@ -20,15 +15,8 @@ class Bar extends Foo { function testBothClass(Foo $foo) {} function testChildClass(Foo $foo) {} function testNoneClass($foo) {} - - function testParentBuiltin($foo) {} - function testBothBuiltin(int $foo) {} - function testChildBuiltin(int $foo) {} - function testNoneBuiltin($foo) {} } ?> --EXPECTF-- -Warning: Declaration of Bar::testChildClass(Foo $foo) should be compatible with Foo::testChildClass($foo) in %s on line %d - -Warning: Declaration of Bar::testChildBuiltin(int $foo) should be compatible with Foo::testChildBuiltin($foo) in %s on line %d +Fatal error: Declaration of Bar::testChildClass(Foo $foo) must be compatible with Foo::testChildClass($foo) in %s on line %d diff --git a/Zend/tests/type_declarations/parameter_type_variance_2.phpt b/Zend/tests/type_declarations/parameter_type_variance_2.phpt new file mode 100644 index 0000000000..59f10b28f5 --- /dev/null +++ b/Zend/tests/type_declarations/parameter_type_variance_2.phpt @@ -0,0 +1,22 @@ +--TEST-- +Parameter variance with no type (builtin) +--FILE-- +<?php + +class Foo { + function testParentBuiltin(int $foo) {} + function testBothBuiltin(int $foo) {} + function testChildBuiltin($foo) {} + function testNoneBuiltin($foo) {} +} + +class Bar extends Foo { + function testParentBuiltin($foo) {} + function testBothBuiltin(int $foo) {} + function testChildBuiltin(int $foo) {} + function testNoneBuiltin($foo) {} +} + +?> +--EXPECTF-- +Fatal error: Declaration of Bar::testChildBuiltin(int $foo) must be compatible with Foo::testChildBuiltin($foo) in %s on line %d diff --git a/Zend/tests/type_declarations/scalar_constant_defaults.phpt b/Zend/tests/type_declarations/scalar_constant_defaults.phpt index b9076c6b52..88c6a4b39f 100644 --- a/Zend/tests/type_declarations/scalar_constant_defaults.phpt +++ b/Zend/tests/type_declarations/scalar_constant_defaults.phpt @@ -39,6 +39,10 @@ function int_val_default_null(int $a = NULL_VAL) { return $a; } +function nullable_int_val_default_null(?int $a = NULL_VAL) { + return $a; +} + echo "Testing int val" . PHP_EOL; var_dump(int_val()); @@ -58,13 +62,27 @@ echo "Testing string add val" . PHP_EOL; var_dump(string_add_val()); echo "Testing int with default null constant" . PHP_EOL; -var_dump(int_val_default_null()); +try { + var_dump(int_val_default_null()); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} echo "Testing int with null null constant" . PHP_EOL; -var_dump(int_val_default_null(null)); +try { + var_dump(int_val_default_null(null)); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +echo "Testing nullable int with default null constant" . PHP_EOL; +var_dump(nullable_int_val_default_null()); + +echo "Testing nullable int with null null constant" . PHP_EOL; +var_dump(nullable_int_val_default_null(null)); ?> ---EXPECT-- +--EXPECTF-- Testing int val int(10) Testing float val @@ -78,6 +96,10 @@ float(10.7) Testing string add val string(14) "this is a test" Testing int with default null constant -NULL +Argument 1 passed to int_val_default_null() must be of the type int, null given, called in %s on line %d Testing int with null null constant +Argument 1 passed to int_val_default_null() must be of the type int, null given, called in %s on line %d +Testing nullable int with default null constant +NULL +Testing nullable int with null null constant NULL diff --git a/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt b/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt index fd7f96ab95..fc6fc21b17 100644 --- a/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt +++ b/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt @@ -12,4 +12,4 @@ test(); ?> --EXPECTF-- -Fatal error: Default value for parameters with a float type can only be float, integer, or NULL in %s on line %d +Fatal error: Cannot use bool as default value for parameter $arg of type float in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_004.phpt b/Zend/tests/type_declarations/typed_properties_004.phpt index 03d9e41aac..2df693aa99 100644 --- a/Zend/tests/type_declarations/typed_properties_004.phpt +++ b/Zend/tests/type_declarations/typed_properties_004.phpt @@ -11,8 +11,8 @@ new class("PHP 7 is better than you, and it knows it ...") { }; ?> --EXPECTF-- -Fatal error: Uncaught TypeError: Typed property class@anonymous::$int must be int, string used in %s:6 +Fatal error: Uncaught TypeError: Cannot assign string to property class@anonymous::$int of type int in %s:%d Stack trace: -#0 %s(2): class@anonymous->__construct('PHP 7 is better...') +#0 %s(%d): class@anonymous->__construct('PHP 7 is better...') #1 {main} - thrown in %s on line 6 + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_005.phpt b/Zend/tests/type_declarations/typed_properties_005.phpt index b521963000..104f4bd57e 100644 --- a/Zend/tests/type_declarations/typed_properties_005.phpt +++ b/Zend/tests/type_declarations/typed_properties_005.phpt @@ -13,8 +13,8 @@ new class(new Dummy) { }; ?> --EXPECTF-- -Fatal error: Uncaught TypeError: Typed property class@anonymous::$std must be an instance of stdClass, Dummy used in %s:8 +Fatal error: Uncaught TypeError: Cannot assign Dummy to property class@anonymous::$std of type stdClass in %s:%d Stack trace: -#0 %s(4): class@anonymous->__construct(Object(Dummy)) +#0 %s(%d): class@anonymous->__construct(Object(Dummy)) #1 {main} - thrown in %s on line 8 + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_013.phpt b/Zend/tests/type_declarations/typed_properties_013.phpt index 01c2f4b6a0..7236e21a2c 100644 --- a/Zend/tests/type_declarations/typed_properties_013.phpt +++ b/Zend/tests/type_declarations/typed_properties_013.phpt @@ -7,4 +7,4 @@ class Foo { } ?> --EXPECTF-- -Fatal error: Default value for property of type int can only be int in %s on line 3 +Fatal error: Cannot use string as default value for property Foo::$bar of type int in %s on line 3 diff --git a/Zend/tests/type_declarations/typed_properties_014.phpt b/Zend/tests/type_declarations/typed_properties_014.phpt index 2a02f0381e..f7a4449abd 100644 --- a/Zend/tests/type_declarations/typed_properties_014.phpt +++ b/Zend/tests/type_declarations/typed_properties_014.phpt @@ -7,4 +7,4 @@ class Foo { } ?> --EXPECTF-- -Fatal error: Default value for property of type array can only be an array in %s on line 3 +Fatal error: Cannot use int as default value for property Foo::$bar of type array in %s on line 3 diff --git a/Zend/tests/type_declarations/typed_properties_020.phpt b/Zend/tests/type_declarations/typed_properties_020.phpt index d32d17b1c8..3b16a9d81d 100644 --- a/Zend/tests/type_declarations/typed_properties_020.phpt +++ b/Zend/tests/type_declarations/typed_properties_020.phpt @@ -22,5 +22,5 @@ $foo = new Foo(); var_dump($foo->bar); ?> --EXPECT-- -Typed property Foo::$bar must be int, float used +Cannot assign float to property Foo::$bar of type int int(2) diff --git a/Zend/tests/type_declarations/typed_properties_029.phpt b/Zend/tests/type_declarations/typed_properties_029.phpt index a5418c91a8..9beca10627 100644 --- a/Zend/tests/type_declarations/typed_properties_029.phpt +++ b/Zend/tests/type_declarations/typed_properties_029.phpt @@ -12,7 +12,7 @@ $foo = new Foo; $foo->bar = "1"; ?> --EXPECTF-- -Fatal error: Uncaught TypeError: Typed property Foo::$bar must be int, string used in %s:9 +Fatal error: Uncaught TypeError: Cannot assign string to property Foo::$bar of type int in %s:%d Stack trace: #0 {main} - thrown in %s on line 9 + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_030.phpt b/Zend/tests/type_declarations/typed_properties_030.phpt index a835ae5fae..8feda02316 100644 --- a/Zend/tests/type_declarations/typed_properties_030.phpt +++ b/Zend/tests/type_declarations/typed_properties_030.phpt @@ -19,7 +19,7 @@ unset($foo->bar); # ok var_dump($foo->bar); # not okay, __get is nasty ?> --EXPECTF-- -Fatal error: Uncaught TypeError: Typed property Foo::$bar must be int, string used in %s:16 +Fatal error: Uncaught TypeError: Cannot assign string to property Foo::$bar of type int in %s:%d Stack trace: #0 {main} - thrown in %s on line 16 + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_034.phpt b/Zend/tests/type_declarations/typed_properties_034.phpt index c3885af39f..79317553ab 100644 --- a/Zend/tests/type_declarations/typed_properties_034.phpt +++ b/Zend/tests/type_declarations/typed_properties_034.phpt @@ -38,7 +38,7 @@ var_dump($foo); ?> --EXPECT-- int(42) -Typed property class@anonymous::$baz must be int, null used +Cannot assign null to property class@anonymous::$baz of type int int(1) int(10) int(10) diff --git a/Zend/tests/type_declarations/typed_properties_038.phpt b/Zend/tests/type_declarations/typed_properties_038.phpt index 44e5d04c7f..94a00d0d8c 100644 --- a/Zend/tests/type_declarations/typed_properties_038.phpt +++ b/Zend/tests/type_declarations/typed_properties_038.phpt @@ -44,7 +44,7 @@ object(class@anonymous)#1 (1) { ["bar"]=> int(%d) } -string(60) "Typed property class@anonymous::$bar must be int, float used" +string(65) "Cannot assign float to property class@anonymous::$bar of type int" object(class@anonymous)#1 (1) { ["bar"]=> int(%d) @@ -54,7 +54,7 @@ object(class@anonymous)#1 (1) { ["bar"]=> int(%d) } -string(60) "Typed property class@anonymous::$bar must be int, float used" +string(65) "Cannot assign float to property class@anonymous::$bar of type int" object(class@anonymous)#1 (1) { ["bar"]=> int(%d) diff --git a/Zend/tests/type_declarations/typed_properties_039.phpt b/Zend/tests/type_declarations/typed_properties_039.phpt index 62413d804c..47ae17f0ab 100644 --- a/Zend/tests/type_declarations/typed_properties_039.phpt +++ b/Zend/tests/type_declarations/typed_properties_039.phpt @@ -25,7 +25,7 @@ var_dump($objs); ?> --EXPECTF-- -Fatal error: Uncaught TypeError: Typed property A::$foo must be int, A used in %s:%d +Fatal error: Uncaught TypeError: Cannot assign A to property A::$foo of type int in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_040.phpt b/Zend/tests/type_declarations/typed_properties_040.phpt index 4da738cb41..d1931c5a11 100644 --- a/Zend/tests/type_declarations/typed_properties_040.phpt +++ b/Zend/tests/type_declarations/typed_properties_040.phpt @@ -20,7 +20,7 @@ var_dump($foo->bar); --EXPECTF-- string(3) "bar" -Fatal error: Uncaught TypeError: Typed property Foo::$bar must be int, null used in %s:%d +Fatal error: Uncaught TypeError: Cannot assign null to property Foo::$bar of type int in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_043.phpt b/Zend/tests/type_declarations/typed_properties_043.phpt index eefe358796..79f01545e1 100644 --- a/Zend/tests/type_declarations/typed_properties_043.phpt +++ b/Zend/tests/type_declarations/typed_properties_043.phpt @@ -41,9 +41,9 @@ var_dump(Bar::$selfProp, Bar::$selfNullProp, Bar::$parentProp); ?> --EXPECT-- -Cannot write a value to a 'self' typed static property of a trait -Cannot write a non-null value to a 'self' typed static property of a trait -Cannot access parent:: when current class scope has no parent +Cannot assign stdClass to property Test::$selfProp of type self +Cannot assign stdClass to property Test::$selfNullProp of type ?self +Cannot assign stdClass to property Test::$parentProp of type parent NULL object(Bar)#3 (0) { } diff --git a/Zend/tests/type_declarations/typed_properties_046.phpt b/Zend/tests/type_declarations/typed_properties_046.phpt index 050e64a2a4..d95fe8dc24 100644 --- a/Zend/tests/type_declarations/typed_properties_046.phpt +++ b/Zend/tests/type_declarations/typed_properties_046.phpt @@ -22,8 +22,8 @@ for ($i = 0; $i < 5; $i++) { } } --EXPECT-- -Typed property Foo::$bbb must be int, string used -Typed property Foo::$bbb must be int, string used -Typed property Foo::$bbb must be int, string used -Typed property Foo::$bbb must be int, string used -Typed property Foo::$bbb must be int, string used +Cannot assign string to property Foo::$bbb of type int +Cannot assign string to property Foo::$bbb of type int +Cannot assign string to property Foo::$bbb of type int +Cannot assign string to property Foo::$bbb of type int +Cannot assign string to property Foo::$bbb of type int diff --git a/Zend/tests/type_declarations/typed_properties_047.phpt b/Zend/tests/type_declarations/typed_properties_047.phpt index 0b48cd1cd4..db78143b02 100644 --- a/Zend/tests/type_declarations/typed_properties_047.phpt +++ b/Zend/tests/type_declarations/typed_properties_047.phpt @@ -37,4 +37,4 @@ NULL int(5) NULL Typed property Foo::$foo must not be accessed before initialization -Typed property Foo::$foo must be int or null, string used +Cannot assign string to property Foo::$foo of type ?int diff --git a/Zend/tests/type_declarations/typed_properties_051.phpt b/Zend/tests/type_declarations/typed_properties_051.phpt index 1c8673d0d3..977570b238 100644 --- a/Zend/tests/type_declarations/typed_properties_051.phpt +++ b/Zend/tests/type_declarations/typed_properties_051.phpt @@ -24,4 +24,4 @@ try { ?> --EXPECT-- string(4) "okok" -Typed property A::$a must be string, C used +Cannot assign C to property A::$a of type string diff --git a/Zend/tests/type_declarations/typed_properties_054.phpt b/Zend/tests/type_declarations/typed_properties_054.phpt index 38de9815ed..cb771d6e64 100644 --- a/Zend/tests/type_declarations/typed_properties_054.phpt +++ b/Zend/tests/type_declarations/typed_properties_054.phpt @@ -9,4 +9,4 @@ $obj = new A; var_dump($obj); ?> --EXPECTF-- -Fatal error: Property A::$a cannot have type callable in %s on line %d +Fatal error: Property A::$a cannot have type ?callable in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_056.phpt b/Zend/tests/type_declarations/typed_properties_056.phpt index 54013f44f2..4d2930cc3b 100644 --- a/Zend/tests/type_declarations/typed_properties_056.phpt +++ b/Zend/tests/type_declarations/typed_properties_056.phpt @@ -19,5 +19,5 @@ var_dump($o->foo); unset($o); ?> --EXPECT-- -Typed property A::$foo must be string, int used +Cannot assign int to property A::$foo of type string string(3) "100" diff --git a/Zend/tests/type_declarations/typed_properties_057.phpt b/Zend/tests/type_declarations/typed_properties_057.phpt index 6b53a42600..ebec0f48bf 100644 --- a/Zend/tests/type_declarations/typed_properties_057.phpt +++ b/Zend/tests/type_declarations/typed_properties_057.phpt @@ -25,7 +25,7 @@ var_dump($o->foo); unset($o); ?> --EXPECT-- -Typed property A::$foo must be string, int used +Cannot assign int to property A::$foo of type string string(3) "100" -Typed property A::$foo must be string, int used +Cannot assign int to property A::$foo of type string string(3) "100" diff --git a/Zend/tests/type_declarations/typed_properties_058.phpt b/Zend/tests/type_declarations/typed_properties_058.phpt index d9283bdbef..a6d65daa4c 100644 --- a/Zend/tests/type_declarations/typed_properties_058.phpt +++ b/Zend/tests/type_declarations/typed_properties_058.phpt @@ -28,5 +28,5 @@ for ($i = 0; $i < 2; $i++) { ?> --EXPECT-- int(5) -Typed property B::$foo must be string, int used -Typed property B::$foo must be string, int used +Cannot assign int to property B::$foo of type string +Cannot assign int to property B::$foo of type string diff --git a/Zend/tests/type_declarations/typed_properties_060.phpt b/Zend/tests/type_declarations/typed_properties_060.phpt index 559349b7a9..5b3c9d0981 100644 --- a/Zend/tests/type_declarations/typed_properties_060.phpt +++ b/Zend/tests/type_declarations/typed_properties_060.phpt @@ -16,7 +16,7 @@ $o->a = "a"; --EXPECTF-- int(1) -Fatal error: Uncaught TypeError: Typed property A::$a must be int, string used in %s:%d +Fatal error: Uncaught TypeError: Cannot assign string to property A::$a of type int in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_068.phpt b/Zend/tests/type_declarations/typed_properties_068.phpt index 7ed58d2a00..dc5cb1b5ff 100644 --- a/Zend/tests/type_declarations/typed_properties_068.phpt +++ b/Zend/tests/type_declarations/typed_properties_068.phpt @@ -69,14 +69,14 @@ int(4) Cannot assign null to reference held by property Foo::$i of type int int(4) int(4) -Typed property Foo::$i must be int, null used +Cannot assign null to property Foo::$i of type int int(4) int(4) string(1) "5" string(1) "5" int(0) int(0) -Typed property Foo::$i must be int, string used +Cannot assign string to property Foo::$i of type int int(0) string(1) "x" Reference with value of type string held by property Foo::$s of type string is not compatible with property Foo::$i of type int diff --git a/Zend/tests/type_declarations/typed_properties_069.phpt b/Zend/tests/type_declarations/typed_properties_069.phpt index 77cfc02487..0f804f8f06 100644 --- a/Zend/tests/type_declarations/typed_properties_069.phpt +++ b/Zend/tests/type_declarations/typed_properties_069.phpt @@ -22,6 +22,6 @@ var_dump(nonNumericStringRef()); ?> --EXPECT-- -Typed property Foo::$i must be int, string used +Cannot assign string to property Foo::$i of type int Typed static property Foo::$i must not be accessed before initialization string(1) "x" diff --git a/Zend/tests/type_declarations/typed_properties_070.phpt b/Zend/tests/type_declarations/typed_properties_070.phpt index dd77c68355..ec2d6bf8c6 100644 --- a/Zend/tests/type_declarations/typed_properties_070.phpt +++ b/Zend/tests/type_declarations/typed_properties_070.phpt @@ -43,7 +43,7 @@ string(2) "11" string(2) "13" string(2) "12" int(1) -Typed property Foo::$i must be int, float used +Cannot assign float to property Foo::$i of type int int(1) -Typed property Foo::$i must be int, string used +Cannot assign string to property Foo::$i of type int int(1) diff --git a/Zend/tests/type_declarations/typed_properties_074.phpt b/Zend/tests/type_declarations/typed_properties_074.phpt index dd2fb5f521..5759505707 100644 --- a/Zend/tests/type_declarations/typed_properties_074.phpt +++ b/Zend/tests/type_declarations/typed_properties_074.phpt @@ -32,7 +32,7 @@ object(Test)#1 (1) { ["val"]=> uninitialized(int) } -Typed property Test::$val must be int, string used +Cannot assign string to property Test::$val of type int object(Test)#1 (1) { ["prop"]=> &string(1) "x" diff --git a/Zend/tests/type_declarations/typed_properties_075.phpt b/Zend/tests/type_declarations/typed_properties_075.phpt index 5f3943cbee..def86f3695 100644 --- a/Zend/tests/type_declarations/typed_properties_075.phpt +++ b/Zend/tests/type_declarations/typed_properties_075.phpt @@ -45,9 +45,9 @@ var_dump(Foo::$bar); --EXPECT-- string(70) "Cannot increment property Foo::$bar of type int past its maximal value" int(9223372036854775807) -string(48) "Typed property Foo::$bar must be int, float used" +string(53) "Cannot assign float to property Foo::$bar of type int" int(9223372036854775807) string(70) "Cannot increment property Foo::$bar of type int past its maximal value" int(9223372036854775807) -string(48) "Typed property Foo::$bar must be int, float used" +string(53) "Cannot assign float to property Foo::$bar of type int" int(9223372036854775807) diff --git a/Zend/tests/type_declarations/typed_properties_078.phpt b/Zend/tests/type_declarations/typed_properties_078.phpt index 6645970dd4..d8fc67d466 100644 --- a/Zend/tests/type_declarations/typed_properties_078.phpt +++ b/Zend/tests/type_declarations/typed_properties_078.phpt @@ -45,7 +45,7 @@ var_dump($ref instanceof ArrayIterator); --EXPECT-- array(0) { } -string(89) "Typed property class@anonymous::$t must be an instance of Traversable or null, array used" +string(72) "Cannot assign array to property class@anonymous::$t of type ?Traversable" array(0) { } array(1) { diff --git a/Zend/tests/type_declarations/typed_properties_091.phpt b/Zend/tests/type_declarations/typed_properties_091.phpt deleted file mode 100644 index 2083086086..0000000000 --- a/Zend/tests/type_declarations/typed_properties_091.phpt +++ /dev/null @@ -1,203 +0,0 @@ ---TEST-- -Automatic promotion of falsy to object ---FILE-- -<?php - -class Test { - public ?Test $prop; - public ?stdClass $stdProp; - public ?object $objectProp; - - public static ?Test $staticProp = null; - public static ?stdClass $staticStdProp = null; - public static ?object $staticObjectProp = null; -} - -// Object properties -$test = new Test; -try { - $test->prop->wat = 123; -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} -$test->stdProp->wat = 123; -$test->objectProp->wat = 123; -var_dump($test); - -// Object properties via reference -$test = new Test; -$prop =& $test->prop; -$stdProp =& $test->stdProp; -$objectProp =& $test->objectProp; -try { - $prop->wat = 123; -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} -$stdProp->wat = 123; -$objectProp->wat = 123; -var_dump($test); - -// Object properties via reference rw -$test = new Test; -$prop =& $test->prop; -$stdProp =& $test->stdProp; -$objectProp =& $test->objectProp; -try { - $prop->wat->wat = 123; -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} -$stdProp->wat->wat = 123; -$objectProp->wat->wat = 123; -var_dump($test); - -// Static properties -try { - Test::$staticProp->wat = 123; -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} -Test::$staticStdProp->wat = 123; -Test::$staticObjectProp->wat = 123; -var_dump(Test::$staticProp, Test::$staticStdProp, Test::$staticObjectProp); - -// Non-string property name -$test = new Test; -$propName = new class { - public function __toString() { - return 'prop'; - } -}; -try { - $test->$propName->wat = 123; -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} -var_dump($test); - -// Initially null -$test = new Test; -$test->prop = NULL; -$test->stdProp = NULL; -$test->objectProp = NULL; -try { - $test->prop->wat = 123; -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} -$test->stdProp->wat = 123; -$test->objectProp->wat = 123; -var_dump($test); - -?> ---EXPECTF-- -Cannot auto-initialize an stdClass inside property Test::$prop of type ?Test - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d -object(Test)#1 (2) { - ["prop"]=> - uninitialized(?Test) - ["stdProp"]=> - object(stdClass)#3 (1) { - ["wat"]=> - int(123) - } - ["objectProp"]=> - object(stdClass)#4 (1) { - ["wat"]=> - int(123) - } -} -Cannot auto-initialize an stdClass inside a reference held by property Test::$prop of type ?Test - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d -object(Test)#5 (3) { - ["prop"]=> - &NULL - ["stdProp"]=> - &object(stdClass)#2 (1) { - ["wat"]=> - int(123) - } - ["objectProp"]=> - &object(stdClass)#4 (1) { - ["wat"]=> - int(123) - } -} -Cannot auto-initialize an stdClass inside a reference held by property Test::$prop of type ?Test - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d -object(Test)#3 (3) { - ["prop"]=> - &NULL - ["stdProp"]=> - &object(stdClass)#1 (1) { - ["wat"]=> - object(stdClass)#2 (1) { - ["wat"]=> - int(123) - } - } - ["objectProp"]=> - &object(stdClass)#5 (1) { - ["wat"]=> - object(stdClass)#6 (1) { - ["wat"]=> - int(123) - } - } -} -Cannot auto-initialize an stdClass inside property Test::$staticProp of type ?Test - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d -NULL -object(stdClass)#4 (1) { - ["wat"]=> - int(123) -} -object(stdClass)#8 (1) { - ["wat"]=> - int(123) -} -Cannot auto-initialize an stdClass inside property Test::$prop of type ?Test -object(Test)#9 (0) { - ["prop"]=> - uninitialized(?Test) - ["stdProp"]=> - uninitialized(?stdClass) - ["objectProp"]=> - uninitialized(?object) -} -Cannot auto-initialize an stdClass inside property Test::$prop of type ?Test - -Warning: Creating default object from empty value in %s on line %d - -Warning: Creating default object from empty value in %s on line %d -object(Test)#7 (3) { - ["prop"]=> - NULL - ["stdProp"]=> - object(stdClass)#10 (1) { - ["wat"]=> - int(123) - } - ["objectProp"]=> - object(stdClass)#11 (1) { - ["wat"]=> - int(123) - } -} diff --git a/Zend/tests/type_declarations/typed_properties_093.phpt b/Zend/tests/type_declarations/typed_properties_093.phpt index f0c7ef51a9..1f4bf4cb8c 100644 --- a/Zend/tests/type_declarations/typed_properties_093.phpt +++ b/Zend/tests/type_declarations/typed_properties_093.phpt @@ -24,7 +24,7 @@ var_dump($test); ?> --EXPECT-- -Typed property Test::$prop must be int, string used +Cannot assign string to property Test::$prop of type int object(Test)#2 (0) { ["prop"]=> uninitialized(int) diff --git a/Zend/tests/type_declarations/typed_properties_095.phpt b/Zend/tests/type_declarations/typed_properties_095.phpt index edbef8dfc7..8470d4f437 100644 --- a/Zend/tests/type_declarations/typed_properties_095.phpt +++ b/Zend/tests/type_declarations/typed_properties_095.phpt @@ -60,25 +60,29 @@ var_dump(_ZendTestClass::$staticIntProp); ?> --EXPECT-- int(123) -Typed property _ZendTestClass::$intProp must be int, string used -Typed property _ZendTestClass::$classProp must be an instance of stdClass or null, _ZendTestClass used -object(_ZendTestClass)#1 (2) { +Cannot assign string to property _ZendTestClass::$intProp of type int +Cannot assign _ZendTestClass to property _ZendTestClass::$classProp of type ?stdClass +object(_ZendTestClass)#1 (3) { ["intProp"]=> int(456) ["classProp"]=> object(stdClass)#2 (0) { } + ["classUnionProp"]=> + NULL } int(123) -Typed property _ZendTestClass::$intProp must be int, string used -Typed property _ZendTestClass::$classProp must be an instance of stdClass or null, Test used -object(Test)#4 (2) { +Cannot assign string to property _ZendTestClass::$intProp of type int +Cannot assign Test to property _ZendTestClass::$classProp of type ?stdClass +object(Test)#4 (3) { ["intProp"]=> int(456) ["classProp"]=> object(stdClass)#1 (0) { } + ["classUnionProp"]=> + NULL } int(123) -Typed property _ZendTestClass::$staticIntProp must be int, string used +Cannot assign string to property _ZendTestClass::$staticIntProp of type int int(456) diff --git a/Zend/tests/type_declarations/typed_properties_096.phpt b/Zend/tests/type_declarations/typed_properties_096.phpt index 32191b241e..83f086d345 100644 --- a/Zend/tests/type_declarations/typed_properties_096.phpt +++ b/Zend/tests/type_declarations/typed_properties_096.phpt @@ -31,7 +31,7 @@ var_dump($test); ?> --EXPECT-- -Typed property Test1::$prop must be an instance of Foobar, int used +Cannot assign int to property Test1::$prop of type Foobar object(Test1)#1 (1) { ["prop"]=> uninitialized(Foobar) diff --git a/Zend/tests/type_declarations/typed_properties_103.phpt b/Zend/tests/type_declarations/typed_properties_103.phpt index 5c0fc85a99..f3f70bfa62 100644 --- a/Zend/tests/type_declarations/typed_properties_103.phpt +++ b/Zend/tests/type_declarations/typed_properties_103.phpt @@ -15,7 +15,7 @@ function foo() { foo(); ?> --EXPECTF-- -Notice: Undefined property: C::$a in %s on line %d +Warning: Undefined property: C::$a in %s on line %d object(C)#1 (1) { ["a"]=> int(2) diff --git a/Zend/tests/type_declarations/typed_properties_class_loading.phpt b/Zend/tests/type_declarations/typed_properties_class_loading.phpt index 0612624454..a81bc5b4fe 100644 --- a/Zend/tests/type_declarations/typed_properties_class_loading.phpt +++ b/Zend/tests/type_declarations/typed_properties_class_loading.phpt @@ -43,9 +43,9 @@ var_dump($test->propY); ?> --EXPECT-- -Typed property Test::$propX must be an instance of X, stdClass used +Cannot assign stdClass to property Test::$propX of type X object(X)#3 (0) { } -Typed property Test::$propY must be an instance of Y or null, stdClass used +Cannot assign stdClass to property Test::$propY of type ?Y object(Y)#4 (0) { } diff --git a/Zend/tests/type_declarations/union_types/generator_return_containing_extra_types.phpt b/Zend/tests/type_declarations/union_types/generator_return_containing_extra_types.phpt new file mode 100644 index 0000000000..7c369090a5 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/generator_return_containing_extra_types.phpt @@ -0,0 +1,21 @@ +--TEST-- +Generator return value has to have Traversable-ish, but may also have extra types +--FILE-- +<?php + +interface I { + public function test(): iterable|false; +} + +class C implements I { + public function test(): iterable|false { + yield; + } +} + +var_dump((new C)->test()); + +?> +--EXPECT-- +object(Generator)#2 (0) { +} diff --git a/Zend/tests/type_declarations/union_types/generator_return_multiple_classes.phpt b/Zend/tests/type_declarations/union_types/generator_return_multiple_classes.phpt new file mode 100644 index 0000000000..8526c65537 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/generator_return_multiple_classes.phpt @@ -0,0 +1,18 @@ +--TEST-- +Generator return type with multiple classes +--FILE-- +<?php + +interface I { + public function test(): Generator|ArrayAccess|array; +} +class C implements I { + function test(): Generator|ArrayAccess|array { + yield; + } +} + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/union_types/illegal_default_value_argument.phpt b/Zend/tests/type_declarations/union_types/illegal_default_value_argument.phpt new file mode 100644 index 0000000000..6c40adc8f2 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/illegal_default_value_argument.phpt @@ -0,0 +1,11 @@ +--TEST-- +Argument default value not legal for any type in the union +--FILE-- +<?php + +function test(int|float $arg = "0") { +} + +?> +--EXPECTF-- +Fatal error: Cannot use string as default value for parameter $arg of type int|float in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/illegal_default_value_property.phpt b/Zend/tests/type_declarations/union_types/illegal_default_value_property.phpt new file mode 100644 index 0000000000..f5941751dc --- /dev/null +++ b/Zend/tests/type_declarations/union_types/illegal_default_value_property.phpt @@ -0,0 +1,12 @@ +--TEST-- +Default value not legal for any type in the union +--FILE-- +<?php + +class Test { + public int|float $prop = "0"; +} + +?> +--EXPECTF-- +Fatal error: Cannot use string as default value for property Test::$prop of type int|float in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/incdec_prop.phpt b/Zend/tests/type_declarations/union_types/incdec_prop.phpt new file mode 100644 index 0000000000..dde6f59526 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/incdec_prop.phpt @@ -0,0 +1,132 @@ +--TEST-- +Increment/decrement a typed property with int|float type +--FILE-- +<?php + +class Test { + public int|float $prop; + public int|bool $prop2; +} + +/* Incrementing a int|float property past int min/max is legal */ + +$test = new Test; +$test->prop = PHP_INT_MAX; +$x = $test->prop++; +var_dump(is_double($test->prop)); + +$test->prop = PHP_INT_MAX; +$x = ++$test->prop; +var_dump(is_double($test->prop)); + +$test->prop = PHP_INT_MIN; +$x = $test->prop--; +var_dump(is_double($test->prop)); + +$test->prop = PHP_INT_MIN; +$x = --$test->prop; +var_dump(is_double($test->prop)); + +$test = new Test; +$test->prop = PHP_INT_MAX; +$r =& $test->prop; +$x = $test->prop++; +var_dump(is_double($test->prop)); + +$test->prop = PHP_INT_MAX; +$x = ++$test->prop; +$r =& $test->prop; +var_dump(is_double($test->prop)); + +$test->prop = PHP_INT_MIN; +$x = $test->prop--; +$r =& $test->prop; +var_dump(is_double($test->prop)); + +$test->prop = PHP_INT_MIN; +$x = --$test->prop; +$r =& $test->prop; +var_dump(is_double($test->prop)); + +/* Incrementing a non-int|float property past int min/max is an error, + * even if the result of the overflow (a float) would technically be allowed + * under a type coercion. */ + +try { + $test->prop2 = PHP_INT_MAX; + $x = $test->prop2++; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->prop2 = PHP_INT_MAX; + $x = ++$test->prop2; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->prop2 = PHP_INT_MIN; + $x = $test->prop2--; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->prop2 = PHP_INT_MIN; + $x = --$test->prop2; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->prop2 = PHP_INT_MAX; + $r =& $test->prop2; + $x = $test->prop2++; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->prop2 = PHP_INT_MAX; + $r =& $test->prop2; + $x = ++$test->prop2; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->prop2 = PHP_INT_MIN; + $r =& $test->prop2; + $x = $test->prop2--; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->prop2 = PHP_INT_MIN; + $r =& $test->prop2; + $x = --$test->prop2; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +Cannot increment property Test::$prop2 of type int|bool past its maximal value +Cannot increment property Test::$prop2 of type int|bool past its maximal value +Cannot decrement property Test::$prop2 of type int|bool past its minimal value +Cannot decrement property Test::$prop2 of type int|bool past its minimal value +Cannot increment a reference held by property Test::$prop2 of type int|bool past its maximal value +Cannot increment a reference held by property Test::$prop2 of type int|bool past its maximal value +Cannot decrement a reference held by property Test::$prop2 of type int|bool past its minimal value +Cannot decrement a reference held by property Test::$prop2 of type int|bool past its minimal value diff --git a/Zend/tests/type_declarations/union_types/inheritance.phpt b/Zend/tests/type_declarations/union_types/inheritance.phpt new file mode 100644 index 0000000000..a0a1b65912 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/inheritance.phpt @@ -0,0 +1,46 @@ +--TEST-- +Various inheritance scenarios for properties/methods with union types +--FILE-- +<?php + +class X { + public A|B|int $prop; + public function method(A|B|int $arg): A|B|int { } + + private A|B|int $prop2; + private function method2(A|B|int $arg): A|B|int { } +} + +class Y extends X { +} + +trait T { + public A|B|int $prop; + public function method(A|B|int $arg): A|B|int { } + + private A|B|int $prop2; + private function method2(A|B|int $arg): A|B|int { } +} + +class Z { + use T; +} + +class U extends X { + use T; +} + +class V extends X { + use T; + + public A|B|int $prop; + public function method(A|B|int $arg): A|B|int { } + + private A|B|int $prop2; + private function method2(A|B|int $arg): A|B|int { } +} + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/union_types/inheritance_internal.phpt b/Zend/tests/type_declarations/union_types/inheritance_internal.phpt new file mode 100644 index 0000000000..bb53411cad --- /dev/null +++ b/Zend/tests/type_declarations/union_types/inheritance_internal.phpt @@ -0,0 +1,33 @@ +--TEST-- +Inheritance of union type from internal class +--SKIPIF-- +<?php +if (!extension_loaded('zend-test')) die('skip requires zend-test extension'); +?> +--FILE-- +<?php + +class C extends _ZendTestClass {} + +$obj = new _ZendTestChildClass; +$obj->classUnionProp = new stdClass; +$obj->classUnionProp = new ArrayIterator; +try { + $obj->classUnionProp = new DateTime; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +$obj = new C; +$obj->classUnionProp = new stdClass; +$obj->classUnionProp = new ArrayIterator; +try { + $obj->classUnionProp = new DateTime; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot assign DateTime to property _ZendTestClass::$classUnionProp of type stdClass|Iterator|null +Cannot assign DateTime to property _ZendTestClass::$classUnionProp of type stdClass|Iterator|null diff --git a/Zend/tests/type_declarations/union_types/legal_default_values.phpt b/Zend/tests/type_declarations/union_types/legal_default_values.phpt new file mode 100644 index 0000000000..2807397734 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/legal_default_values.phpt @@ -0,0 +1,45 @@ +--TEST-- +The default value must be legal for one of the types in the union +--FILE-- +<?php + +class Test { + public int|float $a = 1; + public int|float $b = 2.0; + public float|string $c = 3; // Strict typing exception + public float|string $d = 4.0; + public float|string $e = "5"; +} + +function test( + int|float $a = 1, + int|float $b = 2.0, + float|string $c = 3, // Strict typing exception + float|string $d = 4.0, + float|string $e = "5" +) { + var_dump($a, $b, $c, $d, $e); +} + +var_dump(new Test); +test(); + +?> +--EXPECT-- +object(Test)#1 (5) { + ["a"]=> + int(1) + ["b"]=> + float(2) + ["c"]=> + float(3) + ["d"]=> + float(4) + ["e"]=> + string(1) "5" +} +int(1) +float(2) +float(3) +float(4) +string(1) "5" diff --git a/Zend/tests/type_declarations/union_types/multiple_classes.phpt b/Zend/tests/type_declarations/union_types/multiple_classes.phpt new file mode 100644 index 0000000000..aac56c6603 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/multiple_classes.phpt @@ -0,0 +1,83 @@ +--TEST-- +Union types with multiple classes +--FILE-- +<?php + +class Test { + public X|Y|Z|int $prop; + public function method(X|Y|Z|int $arg): X|Y|Z|int { + return $arg; + } +} + +// Check that nothing here triggers autoloading. +spl_autoload_register(function($class) { + echo "Loading $class\n"; +}); + +$test = new Test; + +$test->prop = 42; +var_dump($test->prop); +var_dump($test->method(42)); + +$test->prop = "42"; +var_dump($test->prop); +var_dump($test->method("42")); + +try { + $test->prop = new stdClass; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $test->method(new stdClass); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +if (true) { + class X {} +} + +$test->prop = new X; +var_dump($test->prop); +var_dump($test->method(new X)); + +if (true) { + class Z {} +} + +$test->prop = new Z; +var_dump($test->prop); +var_dump($test->method(new Z)); + +if (true) { + class Y {} +} + +$test->prop = new Y; +var_dump($test->prop); +var_dump($test->method(new Y)); + +?> +--EXPECTF-- +int(42) +int(42) +int(42) +int(42) +Cannot assign stdClass to property Test::$prop of type X|Y|Z|int +Argument 1 passed to Test::method() must be of type X|Y|Z|int, instance of stdClass given, called in %s on line %d +object(X)#4 (0) { +} +object(X)#6 (0) { +} +object(Z)#6 (0) { +} +object(Z)#4 (0) { +} +object(Y)#4 (0) { +} +object(Y)#6 (0) { +} diff --git a/Zend/tests/type_declarations/union_types/prop_ref_assign.phpt b/Zend/tests/type_declarations/union_types/prop_ref_assign.phpt new file mode 100644 index 0000000000..a8db8fca9c --- /dev/null +++ b/Zend/tests/type_declarations/union_types/prop_ref_assign.phpt @@ -0,0 +1,59 @@ +--TEST-- +Assignments to references that are held by properties with union types +--FILE-- +<?php + +class Test { + public int|string $x; + public float|string $y; +} + +$test = new Test; +$r = "foobar"; +$test->x =& $r; +$test->y =& $r; + +$v = 42; +try { + $r = $v; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +var_dump($r, $v); + +$v = 42.0; +try { + $r = $v; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +var_dump($r, $v); + +unset($r, $test->x, $test->y); + +$test->x = 42; +try { + $test->y =& $test->x; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +unset($test->x, $test->y); + +$test->y = 42.0; +try { + $test->x =& $test->y; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot assign int to reference held by property Test::$x of type string|int and property Test::$y of type string|float, as this would result in an inconsistent type conversion +string(6) "foobar" +int(42) +Cannot assign float to reference held by property Test::$x of type string|int and property Test::$y of type string|float, as this would result in an inconsistent type conversion +string(6) "foobar" +float(42) +Reference with value of type int held by property Test::$x of type string|int is not compatible with property Test::$y of type string|float +Reference with value of type float held by property Test::$y of type string|float is not compatible with property Test::$x of type string|int diff --git a/Zend/tests/type_declarations/union_types/redundant_types/bool_and_false.phpt b/Zend/tests/type_declarations/union_types/redundant_types/bool_and_false.phpt new file mode 100644 index 0000000000..91d2d940f6 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/bool_and_false.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using both bool and false in a union +--FILE-- +<?php + +function test(): bool|false { +} + +?> +--EXPECTF-- +Fatal error: Duplicate type false is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/duplicate_class_type.phpt b/Zend/tests/type_declarations/union_types/redundant_types/duplicate_class_type.phpt new file mode 100644 index 0000000000..5739f699e7 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/duplicate_class_type.phpt @@ -0,0 +1,11 @@ +--TEST-- +Duplicate class type +--FILE-- +<?php + +function test(): Foo|int|FOO { +} + +?> +--EXPECTF-- +Fatal error: Duplicate type FOO is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/duplicate_type.phpt b/Zend/tests/type_declarations/union_types/redundant_types/duplicate_type.phpt new file mode 100644 index 0000000000..f9cd3e01fa --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/duplicate_type.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using a type twice in a union +--FILE-- +<?php + +function test(): int|INT { +} + +?> +--EXPECTF-- +Fatal error: Duplicate type int is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable.phpt b/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable.phpt new file mode 100644 index 0000000000..5b65a33de1 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using both iterable and Traversable +--FILE-- +<?php + +function test(): iterable|Traversable { +} + +?> +--EXPECTF-- +Fatal error: Type Traversable|iterable contains both iterable and Traversable, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable_2.phpt b/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable_2.phpt new file mode 100644 index 0000000000..e3f7c5858b --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_Traversable_2.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using both iterable and Traversable, with extra classes +--FILE-- +<?php + +function test(): iterable|Traversable|ArrayAccess { +} + +?> +--EXPECTF-- +Fatal error: Type Traversable|ArrayAccess|iterable contains both iterable and Traversable, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_array.phpt b/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_array.phpt new file mode 100644 index 0000000000..c6b0949418 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/iterable_and_array.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using both iterable and array +--FILE-- +<?php + +function test(): iterable|array { +} + +?> +--EXPECTF-- +Fatal error: Type iterable|array contains both iterable and array, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/nullable_null.phpt b/Zend/tests/type_declarations/union_types/redundant_types/nullable_null.phpt new file mode 100644 index 0000000000..5597794c86 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/nullable_null.phpt @@ -0,0 +1,11 @@ +--TEST-- +Combining nullability with null +--FILE-- +<?php + +function test(): ?null { +} + +?> +--EXPECTF-- +Fatal error: Null can not be used as a standalone type in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type.phpt b/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type.phpt new file mode 100644 index 0000000000..e9f785ed17 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using both object and a class type +--FILE-- +<?php + +function test(): object|Test { +} + +?> +--EXPECTF-- +Fatal error: Type Test|object contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/standalone_false.phpt b/Zend/tests/type_declarations/union_types/standalone_false.phpt new file mode 100644 index 0000000000..3932f929e5 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/standalone_false.phpt @@ -0,0 +1,10 @@ +--TEST-- +False cannot be used as a standalone type +--FILE-- +<?php + +function test(): false {} + +?> +--EXPECTF-- +Fatal error: False can not be used as a standalone type in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/standalone_null.phpt b/Zend/tests/type_declarations/union_types/standalone_null.phpt new file mode 100644 index 0000000000..7a25f9cd05 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/standalone_null.phpt @@ -0,0 +1,10 @@ +--TEST-- +Null cannot be used as a standalone type +--FILE-- +<?php + +function test(): null {} + +?> +--EXPECTF-- +Fatal error: Null can not be used as a standalone type in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/standalone_nullable_false.phpt b/Zend/tests/type_declarations/union_types/standalone_nullable_false.phpt new file mode 100644 index 0000000000..1e680249b0 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/standalone_nullable_false.phpt @@ -0,0 +1,10 @@ +--TEST-- +Nullable false cannot be used as a standalone type +--FILE-- +<?php + +function test(): ?false {} + +?> +--EXPECTF-- +Fatal error: False can not be used as a standalone type in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/type_checking_strict.phpt b/Zend/tests/type_declarations/union_types/type_checking_strict.phpt new file mode 100644 index 0000000000..f098b638dc --- /dev/null +++ b/Zend/tests/type_declarations/union_types/type_checking_strict.phpt @@ -0,0 +1,211 @@ +--TEST-- +Behavior of union type checks (strict) +--SKIPIF-- +<?php +if (!extension_loaded('json')) die('skip requires json'); +?> +--FILE-- +<?php + +declare(strict_types=1); + +function dump($value) { + if (is_object($value)) { + return 'new ' . get_class($value); + } + if ($value === INF) { + return 'INF'; + } + return json_encode($value, JSON_PRESERVE_ZERO_FRACTION); +} + +function test(string $type, array $values) { + $alignment = 16; + + echo "\nType $type:\n"; + $fn = eval("return function($type \$arg) { return \$arg; };"); + foreach ($values as $value) { + echo str_pad(dump($value), $alignment), ' => '; + + try { + error_clear_last(); + $value = @$fn($value); + echo dump($value); + if ($e = error_get_last()) { + echo ' (', $e['message'], ')'; + } + } catch (TypeError $e) { + $msg = $e->getMessage(); + $msg = strstr($msg, ', called in', true); + $msg = str_replace('1 passed to {closure}()', '...', $msg); + echo $msg; + } + echo "\n"; + } +} + +class WithToString { + public function __toString() { + return "__toString()"; + } +} + +$values = [ + 42, 42.0, INF, "42", "42.0", "42x", "x", "", + true, false, null, [], new stdClass, new WithToString, +]; +test('int|float', $values); +test('int|float|false', $values); +test('int|float|bool', $values); +test('int|bool', $values); +test('int|string|null', $values); +test('string|bool', $values); +test('float|array', $values); +test('string|array', $values); +test('bool|array', $values); + +?> +--EXPECT-- +Type int|float: +42 => 42 +42.0 => 42.0 +INF => INF +"42" => Argument ... must be of type int|float, string given +"42.0" => Argument ... must be of type int|float, string given +"42x" => Argument ... must be of type int|float, string given +"x" => Argument ... must be of type int|float, string given +"" => Argument ... must be of type int|float, string given +true => Argument ... must be of type int|float, bool given +false => Argument ... must be of type int|float, bool given +null => Argument ... must be of type int|float, null given +[] => Argument ... must be of type int|float, array given +new stdClass => Argument ... must be of type int|float, object given +new WithToString => Argument ... must be of type int|float, object given + +Type int|float|false: +42 => 42 +42.0 => 42.0 +INF => INF +"42" => Argument ... must be of type int|float|false, string given +"42.0" => Argument ... must be of type int|float|false, string given +"42x" => Argument ... must be of type int|float|false, string given +"x" => Argument ... must be of type int|float|false, string given +"" => Argument ... must be of type int|float|false, string given +true => Argument ... must be of type int|float|false, bool given +false => false +null => Argument ... must be of type int|float|false, null given +[] => Argument ... must be of type int|float|false, array given +new stdClass => Argument ... must be of type int|float|false, object given +new WithToString => Argument ... must be of type int|float|false, object given + +Type int|float|bool: +42 => 42 +42.0 => 42.0 +INF => INF +"42" => Argument ... must be of type int|float|bool, string given +"42.0" => Argument ... must be of type int|float|bool, string given +"42x" => Argument ... must be of type int|float|bool, string given +"x" => Argument ... must be of type int|float|bool, string given +"" => Argument ... must be of type int|float|bool, string given +true => true +false => false +null => Argument ... must be of type int|float|bool, null given +[] => Argument ... must be of type int|float|bool, array given +new stdClass => Argument ... must be of type int|float|bool, object given +new WithToString => Argument ... must be of type int|float|bool, object given + +Type int|bool: +42 => 42 +42.0 => Argument ... must be of type int|bool, float given +INF => Argument ... must be of type int|bool, float given +"42" => Argument ... must be of type int|bool, string given +"42.0" => Argument ... must be of type int|bool, string given +"42x" => Argument ... must be of type int|bool, string given +"x" => Argument ... must be of type int|bool, string given +"" => Argument ... must be of type int|bool, string given +true => true +false => false +null => Argument ... must be of type int|bool, null given +[] => Argument ... must be of type int|bool, array given +new stdClass => Argument ... must be of type int|bool, object given +new WithToString => Argument ... must be of type int|bool, object given + +Type int|string|null: +42 => 42 +42.0 => Argument ... must be of type string|int|null, float given +INF => Argument ... must be of type string|int|null, float given +"42" => "42" +"42.0" => "42.0" +"42x" => "42x" +"x" => "x" +"" => "" +true => Argument ... must be of type string|int|null, bool given +false => Argument ... must be of type string|int|null, bool given +null => null +[] => Argument ... must be of type string|int|null, array given +new stdClass => Argument ... must be of type string|int|null, object given +new WithToString => Argument ... must be of type string|int|null, object given + +Type string|bool: +42 => Argument ... must be of type string|bool, int given +42.0 => Argument ... must be of type string|bool, float given +INF => Argument ... must be of type string|bool, float given +"42" => "42" +"42.0" => "42.0" +"42x" => "42x" +"x" => "x" +"" => "" +true => true +false => false +null => Argument ... must be of type string|bool, null given +[] => Argument ... must be of type string|bool, array given +new stdClass => Argument ... must be of type string|bool, object given +new WithToString => Argument ... must be of type string|bool, object given + +Type float|array: +42 => 42.0 +42.0 => 42.0 +INF => INF +"42" => Argument ... must be of type array|float, string given +"42.0" => Argument ... must be of type array|float, string given +"42x" => Argument ... must be of type array|float, string given +"x" => Argument ... must be of type array|float, string given +"" => Argument ... must be of type array|float, string given +true => Argument ... must be of type array|float, bool given +false => Argument ... must be of type array|float, bool given +null => Argument ... must be of type array|float, null given +[] => [] +new stdClass => Argument ... must be of type array|float, object given +new WithToString => Argument ... must be of type array|float, object given + +Type string|array: +42 => Argument ... must be of type array|string, int given +42.0 => Argument ... must be of type array|string, float given +INF => Argument ... must be of type array|string, float given +"42" => "42" +"42.0" => "42.0" +"42x" => "42x" +"x" => "x" +"" => "" +true => Argument ... must be of type array|string, bool given +false => Argument ... must be of type array|string, bool given +null => Argument ... must be of type array|string, null given +[] => [] +new stdClass => Argument ... must be of type array|string, object given +new WithToString => Argument ... must be of type array|string, object given + +Type bool|array: +42 => Argument ... must be of type array|bool, int given +42.0 => Argument ... must be of type array|bool, float given +INF => Argument ... must be of type array|bool, float given +"42" => Argument ... must be of type array|bool, string given +"42.0" => Argument ... must be of type array|bool, string given +"42x" => Argument ... must be of type array|bool, string given +"x" => Argument ... must be of type array|bool, string given +"" => Argument ... must be of type array|bool, string given +true => true +false => false +null => Argument ... must be of type array|bool, null given +[] => [] +new stdClass => Argument ... must be of type array|bool, object given +new WithToString => Argument ... must be of type array|bool, object given diff --git a/Zend/tests/type_declarations/union_types/type_checking_weak.phpt b/Zend/tests/type_declarations/union_types/type_checking_weak.phpt new file mode 100644 index 0000000000..441eaab854 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/type_checking_weak.phpt @@ -0,0 +1,209 @@ +--TEST-- +Behavior of union type checks (weak) +--SKIPIF-- +<?php +if (!extension_loaded('json')) die('skip requires json'); +?> +--FILE-- +<?php + +function dump($value) { + if (is_object($value)) { + return 'new ' . get_class($value); + } + if ($value === INF) { + return 'INF'; + } + return json_encode($value, JSON_PRESERVE_ZERO_FRACTION); +} + +function test(string $type, array $values) { + $alignment = 16; + + echo "\nType $type:\n"; + $fn = eval("return function($type \$arg) { return \$arg; };"); + foreach ($values as $value) { + echo str_pad(dump($value), $alignment), ' => '; + + try { + error_clear_last(); + $value = @$fn($value); + echo dump($value); + if ($e = error_get_last()) { + echo ' (', $e['message'], ')'; + } + } catch (TypeError $e) { + $msg = $e->getMessage(); + $msg = strstr($msg, ', called in', true); + $msg = str_replace('1 passed to {closure}()', '...', $msg); + echo $msg; + } + echo "\n"; + } +} + +class WithToString { + public function __toString() { + return "__toString()"; + } +} + +$values = [ + 42, 42.0, INF, "42", "42.0", "42x", "x", "", + true, false, null, [], new stdClass, new WithToString, +]; +test('int|float', $values); +test('int|float|false', $values); +test('int|float|bool', $values); +test('int|bool', $values); +test('int|string|null', $values); +test('string|bool', $values); +test('float|array', $values); +test('string|array', $values); +test('bool|array', $values); + +?> +--EXPECT-- +Type int|float: +42 => 42 +42.0 => 42.0 +INF => INF +"42" => 42 +"42.0" => 42.0 +"42x" => 42 (A non well formed numeric value encountered) +"x" => Argument ... must be of type int|float, string given +"" => Argument ... must be of type int|float, string given +true => 1 +false => 0 +null => Argument ... must be of type int|float, null given +[] => Argument ... must be of type int|float, array given +new stdClass => Argument ... must be of type int|float, object given +new WithToString => Argument ... must be of type int|float, object given + +Type int|float|false: +42 => 42 +42.0 => 42.0 +INF => INF +"42" => 42 +"42.0" => 42.0 +"42x" => 42 (A non well formed numeric value encountered) +"x" => Argument ... must be of type int|float|false, string given +"" => Argument ... must be of type int|float|false, string given +true => 1 +false => false +null => Argument ... must be of type int|float|false, null given +[] => Argument ... must be of type int|float|false, array given +new stdClass => Argument ... must be of type int|float|false, object given +new WithToString => Argument ... must be of type int|float|false, object given + +Type int|float|bool: +42 => 42 +42.0 => 42.0 +INF => INF +"42" => 42 +"42.0" => 42.0 +"42x" => 42 (A non well formed numeric value encountered) +"x" => true +"" => false +true => true +false => false +null => Argument ... must be of type int|float|bool, null given +[] => Argument ... must be of type int|float|bool, array given +new stdClass => Argument ... must be of type int|float|bool, object given +new WithToString => Argument ... must be of type int|float|bool, object given + +Type int|bool: +42 => 42 +42.0 => 42 +INF => true +"42" => 42 +"42.0" => 42 +"42x" => 42 (A non well formed numeric value encountered) +"x" => true +"" => false +true => true +false => false +null => Argument ... must be of type int|bool, null given +[] => Argument ... must be of type int|bool, array given +new stdClass => Argument ... must be of type int|bool, object given +new WithToString => Argument ... must be of type int|bool, object given + +Type int|string|null: +42 => 42 +42.0 => 42 +INF => "INF" +"42" => "42" +"42.0" => "42.0" +"42x" => "42x" +"x" => "x" +"" => "" +true => 1 +false => 0 +null => null +[] => Argument ... must be of type string|int|null, array given +new stdClass => Argument ... must be of type string|int|null, object given +new WithToString => "__toString()" + +Type string|bool: +42 => "42" +42.0 => "42" +INF => "INF" +"42" => "42" +"42.0" => "42.0" +"42x" => "42x" +"x" => "x" +"" => "" +true => true +false => false +null => Argument ... must be of type string|bool, null given +[] => Argument ... must be of type string|bool, array given +new stdClass => Argument ... must be of type string|bool, object given +new WithToString => "__toString()" + +Type float|array: +42 => 42.0 +42.0 => 42.0 +INF => INF +"42" => 42.0 +"42.0" => 42.0 +"42x" => 42.0 (A non well formed numeric value encountered) +"x" => Argument ... must be of type array|float, string given +"" => Argument ... must be of type array|float, string given +true => 1.0 +false => 0.0 +null => Argument ... must be of type array|float, null given +[] => [] +new stdClass => Argument ... must be of type array|float, object given +new WithToString => Argument ... must be of type array|float, object given + +Type string|array: +42 => "42" +42.0 => "42" +INF => "INF" +"42" => "42" +"42.0" => "42.0" +"42x" => "42x" +"x" => "x" +"" => "" +true => "1" +false => "" +null => Argument ... must be of type array|string, null given +[] => [] +new stdClass => Argument ... must be of type array|string, object given +new WithToString => "__toString()" + +Type bool|array: +42 => true +42.0 => true +INF => true +"42" => true +"42.0" => true +"42x" => true +"x" => true +"" => false +true => true +false => false +null => Argument ... must be of type array|bool, null given +[] => [] +new stdClass => Argument ... must be of type array|bool, object given +new WithToString => Argument ... must be of type array|bool, object given diff --git a/Zend/tests/type_declarations/union_types/variance/invalid_001.phpt b/Zend/tests/type_declarations/union_types/variance/invalid_001.phpt new file mode 100644 index 0000000000..9e1dcaefa1 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/variance/invalid_001.phpt @@ -0,0 +1,15 @@ +--TEST-- +Invalid union type variance: Adding extra return type +--FILE-- +<?php + +class A { + public function method(): int {} +} +class B extends A { + public function method(): int|float {} +} + +?> +--EXPECTF-- +Fatal error: Declaration of B::method(): int|float must be compatible with A::method(): int in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/variance/invalid_002.phpt b/Zend/tests/type_declarations/union_types/variance/invalid_002.phpt new file mode 100644 index 0000000000..4448114fce --- /dev/null +++ b/Zend/tests/type_declarations/union_types/variance/invalid_002.phpt @@ -0,0 +1,15 @@ +--TEST-- +Invalid union type variance: Removing argument union type +--FILE-- +<?php + +class A { + public function method(int|float $a) {} +} +class B extends A { + public function method(int $a) {} +} + +?> +--EXPECTF-- +Fatal error: Declaration of B::method(int $a) must be compatible with A::method(int|float $a) in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/variance/invalid_003.phpt b/Zend/tests/type_declarations/union_types/variance/invalid_003.phpt new file mode 100644 index 0000000000..26d9ae3eb4 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/variance/invalid_003.phpt @@ -0,0 +1,18 @@ +--TEST-- +Invalid union type variance: Using parent of class in return type +--FILE-- +<?php + +class X {} +class Y extends X {} + +class A { + public function method(): Y|string {} +} +class B extends A { + public function method(): X|string {} +} + +?> +--EXPECTF-- +Fatal error: Declaration of B::method(): X|string must be compatible with A::method(): Y|string in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/variance/invalid_004.phpt b/Zend/tests/type_declarations/union_types/variance/invalid_004.phpt new file mode 100644 index 0000000000..db16fecbac --- /dev/null +++ b/Zend/tests/type_declarations/union_types/variance/invalid_004.phpt @@ -0,0 +1,13 @@ +--TEST-- +Invalid property inheritance where one direction is valid and the other unresolved +--FILE-- +<?php +class A { + public X|B $prop; +} +class B extends A { + public B $prop; +} +?> +--EXPECTF-- +Fatal error: Type of B::$prop must be X|B (as in class A) in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/variance/valid.phpt b/Zend/tests/type_declarations/union_types/variance/valid.phpt new file mode 100644 index 0000000000..f9e5cc4980 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/variance/valid.phpt @@ -0,0 +1,31 @@ +--TEST-- +Valid union type variance +--FILE-- +<?php + +class X {} +class Y extends X {} + +class A { + public X|Y $prop; + public iterable $prop2; + + public function method(int $a): int|float {} + public function method2(B|string $a): A|string {} + public function method3(Y|B $a): X|A {} + public function method4(Traversable|X $a): iterable|X {} +} +class B extends A { + public X $prop; + public array|Traversable $prop2; + + public function method(int|float $a): int {} + public function method2(A|string $a): B|string {} + public function method3(A|X $a): B|Y {} + public function method4(iterable|X $a): Traversable|X {} +} + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/union_types/void_with_class.phpt b/Zend/tests/type_declarations/union_types/void_with_class.phpt new file mode 100644 index 0000000000..6e1f439e31 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/void_with_class.phpt @@ -0,0 +1,10 @@ +--TEST-- +Combining void with class type +--FILE-- +<?php + +function test(): T|void {} + +?> +--EXPECTF-- +Fatal error: Void can only be used as a standalone type in %s on line %d diff --git a/Zend/tests/type_declarations/variance/class_order_autoload1.phpt b/Zend/tests/type_declarations/variance/class_order_autoload1.phpt index d68d2e8afa..d5ecfa7200 100644 --- a/Zend/tests/type_declarations/variance/class_order_autoload1.phpt +++ b/Zend/tests/type_declarations/variance/class_order_autoload1.phpt @@ -24,7 +24,6 @@ spl_autoload_register(function($class) { var_dump(new C); ?> -===DONE=== --EXPECT-- object(A)#2 (0) { } @@ -34,4 +33,3 @@ object(C)#2 (0) { } object(C)#2 (0) { } -===DONE=== diff --git a/Zend/tests/type_declarations/variance/class_order_autoload2.phpt b/Zend/tests/type_declarations/variance/class_order_autoload2.phpt index f6229d3995..36414f5fe6 100644 --- a/Zend/tests/type_declarations/variance/class_order_autoload2.phpt +++ b/Zend/tests/type_declarations/variance/class_order_autoload2.phpt @@ -25,7 +25,6 @@ spl_autoload_register(function($class) { var_dump(new B); ?> -===DONE=== --EXPECT-- object(A)#2 (0) { } @@ -35,4 +34,3 @@ object(B)#2 (0) { } object(B)#2 (0) { } -===DONE=== diff --git a/Zend/tests/type_declarations/variance/class_order_autoload3.phpt b/Zend/tests/type_declarations/variance/class_order_autoload3.phpt index d09f2a9c45..0f34aa224e 100644 --- a/Zend/tests/type_declarations/variance/class_order_autoload3.phpt +++ b/Zend/tests/type_declarations/variance/class_order_autoload3.phpt @@ -30,7 +30,6 @@ spl_autoload_register(function($class) { var_dump(new B); ?> -===DONE=== --EXPECT-- object(A)#2 (0) { } @@ -42,4 +41,3 @@ object(B)#2 (0) { } object(B)#2 (0) { } -===DONE=== diff --git a/Zend/tests/type_declarations/variance/class_order_autoload4.phpt b/Zend/tests/type_declarations/variance/class_order_autoload4.phpt index 37070b444c..f426f8b44d 100644 --- a/Zend/tests/type_declarations/variance/class_order_autoload4.phpt +++ b/Zend/tests/type_declarations/variance/class_order_autoload4.phpt @@ -31,7 +31,6 @@ spl_autoload_register(function($class) { var_dump(new B); ?> -===DONE=== --EXPECT-- object(A)#2 (0) { } @@ -41,4 +40,3 @@ object(B)#2 (0) { } object(B)#2 (0) { } -===DONE=== diff --git a/Zend/tests/type_declarations/variance/class_order_autoload5.phpt b/Zend/tests/type_declarations/variance/class_order_autoload5.phpt index 77e9a0a9ec..dcb97852aa 100644 --- a/Zend/tests/type_declarations/variance/class_order_autoload5.phpt +++ b/Zend/tests/type_declarations/variance/class_order_autoload5.phpt @@ -41,7 +41,6 @@ spl_autoload_register(function($class) { var_dump(new B); ?> -===DONE=== --EXPECT-- object(A)#2 (0) { } @@ -57,4 +56,3 @@ object(B)#2 (0) { } object(B)#2 (0) { } -===DONE=== diff --git a/Zend/tests/type_declarations/variance/class_order_autoload_error2.phpt b/Zend/tests/type_declarations/variance/class_order_autoload_error2.phpt index 48d2e0b956..4cb4d655d6 100644 --- a/Zend/tests/type_declarations/variance/class_order_autoload_error2.phpt +++ b/Zend/tests/type_declarations/variance/class_order_autoload_error2.phpt @@ -24,4 +24,4 @@ $c = new C; ?> --EXPECTF-- -Warning: Declaration of B::method(C $x) should be compatible with A::method(B $x) in %s on line %d +Fatal error: Declaration of B::method(C $x) must be compatible with A::method(B $x) in %s on line %d diff --git a/Zend/tests/type_declarations/variance/class_order_autoload_error5.phpt b/Zend/tests/type_declarations/variance/class_order_autoload_error5.phpt index a6a46f84a2..ef7032e4a0 100644 --- a/Zend/tests/type_declarations/variance/class_order_autoload_error5.phpt +++ b/Zend/tests/type_declarations/variance/class_order_autoload_error5.phpt @@ -41,12 +41,4 @@ object(A)#2 (0) { object(X)#2 (0) { } -Warning: Declaration of Y::method(Z $a) should be compatible with X::method(Y $a) in %s on line %d -object(Z)#2 (0) { -} -object(Y)#2 (0) { -} -object(B)#2 (0) { -} -object(B)#2 (0) { -} +Fatal error: Declaration of Y::method(Z $a) must be compatible with X::method(Y $a) in %s on line %d diff --git a/Zend/tests/type_declarations/variance/parent_in_class.phpt b/Zend/tests/type_declarations/variance/parent_in_class.phpt deleted file mode 100644 index c65146676d..0000000000 --- a/Zend/tests/type_declarations/variance/parent_in_class.phpt +++ /dev/null @@ -1,47 +0,0 @@ ---TEST-- -Use of parent inside a class that has / has no parent ---FILE-- -<?php - -// Illegal: A::parent is ill-defined -class A { - public function method(parent $x) {} -} -class B extends A { - public function method(parent $x) {} -} - -// Legal: A2::parent == P2 -class P2 {} -class A2 extends P2 { - public function method(parent $x) {} -} -class B2 extends A2 { - public function method(P2 $x) {} -} - -// Legal: B3::parent == A3 is subclass of A3::parent == P3 in covariant position -class P3 {} -class A3 extends P3 { - public function method($x): parent {} -} -class B3 extends A3 { - public function method($x): parent {} -} - -// Illegal: B4::parent == A4 is subclass of A4::parent == P4 in contravariant position -class P4 {} -class A4 extends P4 { - public function method(parent $x) {} -} -class B4 extends A4 { - public function method(parent $x) {} -} - -?> ---EXPECTF-- -Deprecated: Cannot use "parent" when current class scope has no parent in %s on line %d - -Warning: Declaration of B4::method(A4 $x) should be compatible with A4::method(P4 $x) in %s on line %d - -Warning: Could not check compatibility between B::method(A $x) and A::method(parent $x), because class parent is not available in %s on line %d diff --git a/Zend/tests/type_declarations/variance/parent_in_class_failure1.phpt b/Zend/tests/type_declarations/variance/parent_in_class_failure1.phpt new file mode 100644 index 0000000000..6bbf4881a8 --- /dev/null +++ b/Zend/tests/type_declarations/variance/parent_in_class_failure1.phpt @@ -0,0 +1,16 @@ +--TEST-- +Use of parent inside a class that has / has no parent (failure case 1) +--FILE-- +<?php + +// Illegal: A::parent is ill-defined +class A { + public function method(parent $x) {} +} +class B extends A { + public function method(parent $x) {} +} + +?> +--EXPECTF-- +Fatal error: Cannot use "parent" when current class scope has no parent in %s on line %d diff --git a/Zend/tests/type_declarations/variance/parent_in_class_failure2.phpt b/Zend/tests/type_declarations/variance/parent_in_class_failure2.phpt new file mode 100644 index 0000000000..f9902d8073 --- /dev/null +++ b/Zend/tests/type_declarations/variance/parent_in_class_failure2.phpt @@ -0,0 +1,17 @@ +--TEST-- +Use of parent inside a class that has / has no parent (failure case 2) +--FILE-- +<?php + +// Illegal: B4::parent == A4 is subclass of A4::parent == P4 in contravariant position +class P4 {} +class A4 extends P4 { + public function method(parent $x) {} +} +class B4 extends A4 { + public function method(parent $x) {} +} + +?> +--EXPECTF-- +Fatal error: Declaration of B4::method(A4 $x) must be compatible with A4::method(P4 $x) in %s on line %d diff --git a/Zend/tests/type_declarations/variance/parent_in_class_success.phpt b/Zend/tests/type_declarations/variance/parent_in_class_success.phpt new file mode 100644 index 0000000000..c3edceaf3b --- /dev/null +++ b/Zend/tests/type_declarations/variance/parent_in_class_success.phpt @@ -0,0 +1,27 @@ +--TEST-- +Use of parent inside a class that has / has no parent (success cases) +--FILE-- +<?php + +// Legal: A2::parent == P2 +class P2 {} +class A2 extends P2 { + public function method(parent $x) {} +} +class B2 extends A2 { + public function method(P2 $x) {} +} + +// Legal: B3::parent == A3 is subclass of A3::parent == P3 in covariant position +class P3 {} +class A3 extends P3 { + public function method($x): parent {} +} +class B3 extends A3 { + public function method($x): parent {} +} + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/unexpected_ref_bug.phpt b/Zend/tests/unexpected_ref_bug.phpt index a4e74e7a67..0d78410d1a 100644 --- a/Zend/tests/unexpected_ref_bug.phpt +++ b/Zend/tests/unexpected_ref_bug.phpt @@ -9,12 +9,11 @@ class Test { return ","; } } -$my_var = str_repeat("A",64); -$data = call_user_func_array("explode",array(new Test(), &$my_var)); -$my_var=array(1,2,3); -$data = call_user_func_array("implode",array(&$my_var, new Test())); +$my_var = str_repeat("A", 64); +$data = call_user_func_array("explode", array(new Test(), &$my_var)); +$my_var = str_repeat("A", 64); +$data = call_user_func_array("str_replace", array(&$my_var, new Test(), "foo")); echo "Done.\n"; ?> --EXPECTF-- -Deprecated: implode(): Passing glue string after array is deprecated. Swap the parameters in %s on line %d Done. diff --git a/Zend/tests/unset_cast_deprecated.phpt b/Zend/tests/unset_cast_deprecated.phpt deleted file mode 100644 index 6744c85f02..0000000000 --- a/Zend/tests/unset_cast_deprecated.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -The (unset) cast is deprecated ---FILE-- -<?php - -$x = 1; -var_dump((unset) $x); -var_dump($x); - -?> ---EXPECTF-- -Deprecated: The (unset) cast is deprecated in %s on line %d -NULL -int(1) diff --git a/Zend/tests/unset_cast_removed.phpt b/Zend/tests/unset_cast_removed.phpt new file mode 100644 index 0000000000..9f2f798ed0 --- /dev/null +++ b/Zend/tests/unset_cast_removed.phpt @@ -0,0 +1,12 @@ +--TEST-- +The (unset) cast is removed +--FILE-- +<?php + +$x = 1; +var_dump((unset) $x); +var_dump($x); + +?> +--EXPECTF-- +Fatal error: The (unset) cast is no longer supported in %s on line %d diff --git a/Zend/tests/unset_cv01.phpt b/Zend/tests/unset_cv01.phpt index 99af118d10..508a0cbf3e 100644 --- a/Zend/tests/unset_cv01.phpt +++ b/Zend/tests/unset_cv01.phpt @@ -10,4 +10,4 @@ echo $x; --EXPECTF-- ok -Notice: Undefined variable: x in %sunset_cv01.php on line %d +Warning: Undefined variable: x in %s on line %d diff --git a/Zend/tests/unset_cv02.phpt b/Zend/tests/unset_cv02.phpt index cb2475350c..915b165eca 100644 --- a/Zend/tests/unset_cv02.phpt +++ b/Zend/tests/unset_cv02.phpt @@ -10,4 +10,4 @@ echo $x; --EXPECTF-- ok -Notice: Undefined variable: x in %sunset_cv02.php on line %d +Warning: Undefined variable: x in %s on line %d diff --git a/Zend/tests/unset_cv03.phpt b/Zend/tests/unset_cv03.phpt index 221abe2d88..dce3fce5f1 100644 --- a/Zend/tests/unset_cv03.phpt +++ b/Zend/tests/unset_cv03.phpt @@ -10,4 +10,4 @@ echo $x; --EXPECTF-- ok -Notice: Undefined variable: x in %sunset_cv03.php on line %d +Warning: Undefined variable: x in %s on line %d diff --git a/Zend/tests/unset_cv04.phpt b/Zend/tests/unset_cv04.phpt index 5044cb1c8d..816a5f9ce4 100644 --- a/Zend/tests/unset_cv04.phpt +++ b/Zend/tests/unset_cv04.phpt @@ -13,4 +13,4 @@ f(); --EXPECTF-- ok -Notice: Undefined variable: x in %sunset_cv04.php on line %d +Warning: Undefined variable: x in %s on line %d diff --git a/Zend/tests/unset_cv05.phpt b/Zend/tests/unset_cv05.phpt index 073ee4bee4..a389d651ad 100644 --- a/Zend/tests/unset_cv05.phpt +++ b/Zend/tests/unset_cv05.phpt @@ -17,6 +17,6 @@ echo $_SESSION; echo "\nok\n"; ?> --EXPECTF-- -Notice: Array to string conversion in %sunset_cv05.php on line %d +Warning: Array to string conversion in %s on line %d Array ok diff --git a/Zend/tests/unset_cv09.phpt b/Zend/tests/unset_cv09.phpt index a5407ad64e..a52062575c 100644 --- a/Zend/tests/unset_cv09.phpt +++ b/Zend/tests/unset_cv09.phpt @@ -10,5 +10,5 @@ echo "ok\n"; --EXPECTF-- ok -Notice: Undefined variable: x in %sunset_cv09.php on line %d +Warning: Undefined variable: x in %s on line %d ok diff --git a/Zend/tests/unset_cv10.phpt b/Zend/tests/unset_cv10.phpt index 335463b0ca..97a79bb973 100644 --- a/Zend/tests/unset_cv10.phpt +++ b/Zend/tests/unset_cv10.phpt @@ -12,5 +12,5 @@ echo "ok\n"; --EXPECTF-- ok -Notice: Undefined variable: x in %sunset_cv10.php on line %d +Warning: Undefined variable: x in %s on line %d ok diff --git a/Zend/tests/unterminated_comment.phpt b/Zend/tests/unterminated_comment.phpt new file mode 100644 index 0000000000..8a0fb34a2a --- /dev/null +++ b/Zend/tests/unterminated_comment.phpt @@ -0,0 +1,8 @@ +--TEST-- +Unterminated comment +--FILE-- +<?php +/* Foo +Bar +--EXPECTF-- +Parse error: Unterminated comment starting line 2 in %s on line %d diff --git a/Zend/tests/varSyntax/propertyOfStringError.phpt b/Zend/tests/varSyntax/propertyOfStringError.phpt index 4fa50e7df0..446f1372cd 100644 --- a/Zend/tests/varSyntax/propertyOfStringError.phpt +++ b/Zend/tests/varSyntax/propertyOfStringError.phpt @@ -7,4 +7,4 @@ Cannot take property of a string ?> --EXPECTF-- -Notice: Trying to get property 'bar' of non-object in %s on line %d +Warning: Trying to get property 'bar' of non-object in %s on line %d diff --git a/Zend/tests/warning_during_heredoc_scan_ahead.phpt b/Zend/tests/warning_during_heredoc_scan_ahead.phpt deleted file mode 100644 index 099d1c087f..0000000000 --- a/Zend/tests/warning_during_heredoc_scan_ahead.phpt +++ /dev/null @@ -1,20 +0,0 @@ ---TEST-- -No warnings should be thrown during heredoc scan-ahead ---FILE-- -<?php - -<<<TEST -${x} -\400 -${/*} -TEST; - -?> ---EXPECTF-- -Warning: Unexpected character in input: '' (ASCII=1) state=0 in %s on line %d - -Warning: Octal escape sequence overflow \400 is greater than \377 in %s on line %d - -Warning: Unterminated comment starting line %d in %s on line %d - -Parse error: syntax error, unexpected end of file in %s on line %d diff --git a/Zend/zend.c b/Zend/zend.c index 97ac3327ca..3561b36af1 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -94,7 +94,7 @@ ZEND_API zend_bool zend_rc_debug = 0; static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */ { if (!new_value) { - EG(error_reporting) = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED; + EG(error_reporting) = E_ALL; } else { EG(error_reporting) = atoi(ZSTR_VAL(new_value)); } @@ -594,12 +594,20 @@ static void function_copy_ctor(zval *zv) /* {{{ */ new_arg_info = pemalloc(sizeof(zend_arg_info) * num_args, 1); memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args); for (i = 0 ; i < num_args; i++) { - if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { + if (ZEND_TYPE_HAS_LIST(arg_info[i].type)) { + zend_type_list *old_list = ZEND_TYPE_LIST(arg_info[i].type); + zend_type_list *new_list = pemalloc(ZEND_TYPE_LIST_SIZE(old_list->num_types), 1); + memcpy(new_list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types)); + ZEND_TYPE_SET_PTR(new_arg_info[i].type, new_list); + + void **entry; + ZEND_TYPE_LIST_FOREACH_PTR(new_list, entry) { + zend_string *name = zend_string_dup(ZEND_TYPE_LIST_GET_NAME(*entry), 1); + *entry = ZEND_TYPE_LIST_ENCODE_NAME(name); + } ZEND_TYPE_LIST_FOREACH_END(); + } else if (ZEND_TYPE_HAS_NAME(arg_info[i].type)) { zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1); - - new_arg_info[i].type = - ZEND_TYPE_ENCODE_CLASS( - name, ZEND_TYPE_ALLOW_NULL(arg_info[i].type)); + ZEND_TYPE_SET_PTR(new_arg_info[i].type, name); } } func->common.arg_info = new_arg_info + 1; @@ -952,6 +960,15 @@ void zend_register_standard_ini_entries(void) /* {{{ */ } /* }}} */ +static zend_class_entry *resolve_type_name(zend_string *type_name) { + zend_string *lc_type_name = zend_string_tolower(type_name); + zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lc_type_name); + + ZEND_ASSERT(ce && ce->type == ZEND_INTERNAL_CLASS); + zend_string_release(lc_type_name); + return ce; +} + static void zend_resolve_property_types(void) /* {{{ */ { zend_class_entry *ce; @@ -964,14 +981,18 @@ static void zend_resolve_property_types(void) /* {{{ */ if (UNEXPECTED(ZEND_CLASS_HAS_TYPE_HINTS(ce))) { ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) { - if (ZEND_TYPE_IS_NAME(prop_info->type)) { + if (ZEND_TYPE_HAS_LIST(prop_info->type)) { + void **entry; + ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(prop_info->type), entry) { + if (ZEND_TYPE_LIST_IS_NAME(*entry)) { + zend_string *type_name = ZEND_TYPE_LIST_GET_NAME(*entry); + *entry = ZEND_TYPE_LIST_ENCODE_CE(resolve_type_name(type_name)); + zend_string_release(type_name); + } + } ZEND_TYPE_LIST_FOREACH_END(); + } else if (ZEND_TYPE_HAS_NAME(prop_info->type)) { zend_string *type_name = ZEND_TYPE_NAME(prop_info->type); - zend_string *lc_type_name = zend_string_tolower(type_name); - zend_class_entry *prop_ce = zend_hash_find_ptr(CG(class_table), lc_type_name); - - ZEND_ASSERT(prop_ce && prop_ce->type == ZEND_INTERNAL_CLASS); - prop_info->type = ZEND_TYPE_ENCODE_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type)); - zend_string_release(lc_type_name); + ZEND_TYPE_SET_CE(prop_info->type, resolve_type_name(type_name)); zend_string_release(type_name); } } ZEND_HASH_FOREACH_END(); @@ -1144,7 +1165,7 @@ ZEND_API void zend_append_version_info(const zend_extension *extension) /* {{{ * } /* }}} */ -ZEND_API char *get_zend_version(void) /* {{{ */ +ZEND_API const char *get_zend_version(void) /* {{{ */ { return zend_version_info; } @@ -1248,19 +1269,19 @@ ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */ } while (0) static ZEND_COLD void zend_error_va_list( - int type, const char *error_filename, uint32_t error_lineno, + int orig_type, const char *error_filename, uint32_t error_lineno, const char *format, va_list args) { va_list usr_copy; - zval params[5]; + zval params[4]; zval retval; zval orig_user_error_handler; zend_bool in_compilation; zend_class_entry *saved_class_entry; zend_stack loop_var_stack; zend_stack delayed_oplines_stack; - zend_array *symbol_table; zend_class_entry *orig_fake_scope; + int type = orig_type & E_ALL; /* Report about uncaught exception in case of fatal errors */ if (EG(exception)) { @@ -1307,7 +1328,7 @@ static ZEND_COLD void zend_error_va_list( if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF || !(EG(user_error_handler_error_reporting) & type) || EG(error_handling) != EH_NORMAL) { - zend_error_cb(type, error_filename, error_lineno, format, args); + zend_error_cb(orig_type, error_filename, error_lineno, format, args); } else switch (type) { case E_ERROR: case E_PARSE: @@ -1316,7 +1337,7 @@ static ZEND_COLD void zend_error_va_list( case E_COMPILE_ERROR: case E_COMPILE_WARNING: /* The error may not be safe to handle in user-space */ - zend_error_cb(type, error_filename, error_lineno, format, args); + zend_error_cb(orig_type, error_filename, error_lineno, format, args); break; default: /* Handle the error in user space */ @@ -1334,15 +1355,6 @@ static ZEND_COLD void zend_error_va_list( ZVAL_LONG(¶ms[3], error_lineno); - symbol_table = zend_rebuild_symbol_table(); - - /* during shutdown the symbol table table can be still null */ - if (!symbol_table) { - ZVAL_NULL(¶ms[4]); - } else { - ZVAL_ARR(¶ms[4], zend_array_dup(symbol_table)); - } - ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); ZVAL_UNDEF(&EG(user_error_handler)); @@ -1363,16 +1375,16 @@ static ZEND_COLD void zend_error_va_list( orig_fake_scope = EG(fake_scope); EG(fake_scope) = NULL; - if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params) == SUCCESS) { + if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params) == SUCCESS) { if (Z_TYPE(retval) != IS_UNDEF) { if (Z_TYPE(retval) == IS_FALSE) { - zend_error_cb(type, error_filename, error_lineno, format, args); + zend_error_cb(orig_type, error_filename, error_lineno, format, args); } zval_ptr_dtor(&retval); } } else if (!EG(exception)) { /* The user error handler failed, use built-in error handler */ - zend_error_cb(type, error_filename, error_lineno, format, args); + zend_error_cb(orig_type, error_filename, error_lineno, format, args); } EG(fake_scope) = orig_fake_scope; @@ -1384,7 +1396,6 @@ static ZEND_COLD void zend_error_va_list( CG(in_compilation) = 1; } - zval_ptr_dtor(¶ms[4]); zval_ptr_dtor(¶ms[2]); zval_ptr_dtor(¶ms[1]); @@ -1560,37 +1571,28 @@ ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) /* {{{ */ va_end(va); } /* }}} */ -ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) /* {{{ */ +ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) /* {{{ */ { va_list va; char *message = NULL; va_start(va, format); zend_vspprintf(&message, 0, format, va); - if (throw_exception) { - zend_throw_exception(zend_ce_type_error, message, 0); - } else { - zend_error(E_WARNING, "%s", message); - } + zend_throw_exception(zend_ce_argument_count_error, message, 0); efree(message); va_end(va); } /* }}} */ -ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) /* {{{ */ +ZEND_API ZEND_COLD void zend_value_error(const char *format, ...) /* {{{ */ { va_list va; char *message = NULL; va_start(va, format); zend_vspprintf(&message, 0, format, va); - if (throw_exception) { - zend_throw_exception(zend_ce_argument_count_error, message, 0); - } else { - zend_error(E_WARNING, "%s", message); - } + zend_throw_exception(zend_ce_value_error, message, 0); efree(message); - va_end(va); } /* }}} */ @@ -1648,9 +1650,10 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) / int i; zend_file_handle *file_handle; zend_op_array *op_array; + int ret = SUCCESS; va_start(files, file_count); - for (i = 0; i < file_count; i++) { + for (i = 0; i < file_count && ret != FAILURE; i++) { file_handle = va_arg(files, zend_file_handle *); if (!file_handle) { continue; @@ -1670,18 +1673,18 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) / } if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR); + ret = FAILURE; } } destroy_op_array(op_array); efree_size(op_array, sizeof(zend_op_array)); } else if (type==ZEND_REQUIRE) { - va_end(files); - return FAILURE; + ret = FAILURE; } } va_end(files); - return SUCCESS; + return ret; } /* }}} */ diff --git a/Zend/zend.h b/Zend/zend.h index 9aefc8d26a..b965a765e3 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "3.4.0" +#define ZEND_VERSION "4.0.0-dev" #define ZEND_ENGINE_3 @@ -244,7 +244,7 @@ ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) Z ZEND_API size_t zend_spprintf_unchecked(char **message, size_t max_len, const char *format, ...); ZEND_API zend_string *zend_strpprintf_unchecked(size_t max_len, const char *format, ...); -ZEND_API char *get_zend_version(void); +ZEND_API const char *get_zend_version(void); ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy); ZEND_API size_t zend_print_zval(zval *expr, int indent); ZEND_API void zend_print_zval_r(zval *expr, int indent); @@ -300,8 +300,8 @@ ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn(int type, const cha ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2); -ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); -ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); +ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2); +ZEND_API ZEND_COLD void zend_value_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2); ZEND_COLD void zenderror(const char *error); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 4511368bea..34b97b67e7 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -91,12 +91,12 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */ const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_argument_count_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name()); + zend_argument_count_error("Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name()); } /* }}} */ /* Argument parsing API -- andrei */ -ZEND_API char *zend_get_type_by_const(int type) /* {{{ */ +ZEND_API const char *zend_get_type_by_const(int type) /* {{{ */ { switch(type) { case IS_FALSE: @@ -131,7 +131,7 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */ } /* }}} */ -ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */ +ZEND_API const char *zend_zval_type_name(const zval *arg) /* {{{ */ { ZVAL_DEREF(arg); return zend_get_type_by_const(Z_TYPE_P(arg)); @@ -174,28 +174,7 @@ ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* { zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - zend_internal_argument_count_error( - ZEND_ARG_USES_STRICT_TYPES(), - "%s%s%s() expects %s %d parameter%s, %d given", - class_name, \ - class_name[0] ? "::" : "", \ - ZSTR_VAL(active_function->common.function_name), - "exactly", - 0, - "s", - num_args); - return FAILURE; -} -/* }}} */ - -ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void) /* {{{ */ -{ - int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); - zend_function *active_function = EG(current_execute_data)->func; - const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - - zend_internal_argument_count_error( - 1, + zend_argument_count_error( "%s%s%s() expects %s %d parameter%s, %d given", class_name, \ class_name[0] ? "::" : "", \ @@ -214,27 +193,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_ zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - zend_internal_argument_count_error( - ZEND_ARG_USES_STRICT_TYPES(), - "%s%s%s() expects %s %d parameter%s, %d given", - class_name, \ - class_name[0] ? "::" : "", \ - ZSTR_VAL(active_function->common.function_name), - min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most", - num_args < min_num_args ? min_num_args : max_num_args, - (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s", - num_args); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args) /* {{{ */ -{ - int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); - zend_function *active_function = EG(current_execute_data)->func; - const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - - zend_internal_argument_count_error( - 1, + zend_argument_count_error( "%s%s%s() expects %s %d parameter%s, %d given", class_name, \ class_name[0] ? "::" : "", \ @@ -259,44 +218,12 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, z return; } class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given", - class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg)); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg) /* {{{ */ -{ - const char *space; - const char *class_name; - static const char * const expected_error[] = { - Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR) - NULL - }; - - if (EG(exception)) { - return; - } - class_name = get_active_class_name(&space); - zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given", + zend_type_error("%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg)); } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg) /* {{{ */ -{ - const char *space; - const char *class_name; - - if (EG(exception)) { - return; - } - class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given", - class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg)); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, const char *name, zval *arg) /* {{{ */ { const char *space; const char *class_name; @@ -305,7 +232,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int n return; } class_name = get_active_class_name(&space); - zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given", + zend_type_error("%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg)); } /* }}} */ @@ -319,33 +246,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e return; } class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s", - class_name, space, get_active_function_name(), num, error); - efree(error); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error) /* {{{ */ -{ - const char *space; - const char *class_name; - - if (EG(exception)) { - return; - } - class_name = get_active_class_name(&space); - zend_internal_type_error(1, "%s%s%s() expects parameter %d to be a valid callback, %s", - class_name, space, get_active_function_name(), num, error); - efree(error); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_deprecated(int num, char *error) /* {{{ */ -{ - const char *space; - const char *class_name = get_active_class_name(&space); - - zend_error(E_DEPRECATED, "%s%s%s() expects parameter %d to be a valid callback, %s", + zend_type_error("%s%s%s() expects parameter %d to be a valid callback, %s", class_name, space, get_active_function_name(), num, error); efree(error); } @@ -370,7 +271,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pc const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", + zend_type_error("%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", class_name, space, get_active_function_name(), num, ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg)); *pce = NULL; @@ -381,7 +282,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pc const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid class name, '%s' given", + zend_type_error("%s%s%s() expects parameter %d to be a valid class name, '%s' given", class_name, space, get_active_function_name(), num, Z_STRVAL_P(arg)); return 0; @@ -462,50 +363,6 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest) } /* }}} */ -ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *dest) /* {{{ */ -{ - if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) { - if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) { - return 0; - } - *dest = zend_dval_to_lval_cap(Z_DVAL_P(arg)); - } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { - double d; - int type; - - if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) { - if (EXPECTED(type != 0)) { - if (UNEXPECTED(zend_isnan(d))) { - return 0; - } - *dest = zend_dval_to_lval_cap(d); - } else { - return 0; - } - } - if (UNEXPECTED(EG(exception))) { - return 0; - } - } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) { - *dest = 0; - } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) { - *dest = 1; - } else { - return 0; - } - return 1; -} -/* }}} */ - -ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_slow(zval *arg, zend_long *dest) /* {{{ */ -{ - if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) { - return 0; - } - return zend_parse_arg_long_cap_weak(arg, dest); -} -/* }}} */ - ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) { @@ -547,36 +404,52 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest) / } /* }}} */ +ZEND_API int ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest) /* {{{ */ +{ + if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) { + return 0; + } + if (Z_TYPE_P(arg) == IS_STRING) { + zend_string *str = Z_STR_P(arg); + zend_long lval; + double dval; + zend_uchar type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &lval, &dval, -1); + if (type == IS_LONG) { + ZVAL_LONG(arg, lval); + } else if (type == IS_DOUBLE) { + ZVAL_DOUBLE(arg, dval); + } else { + return 0; + } + zend_string_release(str); + } else if (Z_TYPE_P(arg) < IS_TRUE) { + ZVAL_LONG(arg, 0); + } else if (Z_TYPE_P(arg) == IS_TRUE) { + ZVAL_LONG(arg, 1); + } else { + return 0; + } + *dest = arg; + return 1; +} +/* }}} */ + ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) { convert_to_string(arg); *dest = Z_STR_P(arg); } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(arg); + if (Z_OBJ_HANDLER_P(arg, cast_object)) { zval obj; - if (Z_OBJ_HANDLER_P(arg, cast_object)(arg, &obj, IS_STRING) == SUCCESS) { - zval_ptr_dtor(arg); + if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) { + OBJ_RELEASE(zobj); ZVAL_COPY_VALUE(arg, &obj); *dest = Z_STR_P(arg); return 1; } - } else if (Z_OBJ_HANDLER_P(arg, get)) { - zval rv; - zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv); - - if (Z_TYPE_P(z) != IS_OBJECT) { - zval_ptr_dtor(arg); - if (Z_TYPE_P(z) == IS_STRING) { - ZVAL_COPY_VALUE(arg, z); - } else { - ZVAL_STR(arg, zval_get_string_func(z)); - zval_ptr_dtor(z); - } - *dest = Z_STR_P(arg); - return 1; - } - zval_ptr_dtor(z); } return 0; } else { @@ -595,7 +468,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest } /* }}} */ -static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity) /* {{{ */ +static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error) /* {{{ */ { const char *spec_walk = *spec; char c = *spec_walk++; @@ -620,7 +493,6 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons switch (c) { case 'l': - case 'L': { zend_long *p = va_arg(*va, zend_long *); zend_bool *is_null = NULL; @@ -629,7 +501,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons is_null = va_arg(*va, zend_bool *); } - if (!zend_parse_arg_long(arg, p, is_null, check_null, c == 'L')) { + if (!zend_parse_arg_long(arg, p, is_null, check_null)) { return "int"; } } @@ -810,23 +682,16 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons } if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) { - if (is_callable_error) { - *severity = E_DEPRECATED; - zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); - efree(is_callable_error); - *spec = spec_walk; - return ""; - } + ZEND_ASSERT(!is_callable_error); break; + } + + if (is_callable_error) { + zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); + efree(is_callable_error); + return ""; } else { - if (is_callable_error) { - *severity = E_ERROR; - zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); - efree(is_callable_error); - return ""; - } else { - return "valid callback"; - } + return "valid callback"; } } @@ -838,9 +703,9 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons } break; - case 'Z': - /* 'Z' iz not supported anymore and should be replaced with 'z' */ - ZEND_ASSERT(c != 'Z'); + case 'Z': /* replace with 'z' */ + case 'L': /* replace with 'l' */ + ZEND_ASSERT(0 && "ZPP modifier no longer supported"); default: return "unknown"; } @@ -855,9 +720,8 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec { const char *expected_type = NULL; char *error = NULL; - int severity = 0; - expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity); + expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error); if (expected_type) { if (EG(exception)) { return FAILURE; @@ -865,23 +729,18 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) { const char *space; const char *class_name = get_active_class_name(&space); - zend_bool throw_exception = - ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW); if (error) { - zend_internal_type_error(throw_exception, "%s%s%s() expects parameter %d %s", + zend_type_error("%s%s%s() expects parameter %d %s", class_name, space, get_active_function_name(), arg_num, error); efree(error); } else { - zend_internal_type_error(throw_exception, - "%s%s%s() expects parameter %d to be %s, %s given", + zend_type_error("%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), arg_num, expected_type, zend_zval_type_name(arg)); } } - if (severity != E_DEPRECATED) { - return FAILURE; - } + return FAILURE; } return SUCCESS; @@ -983,8 +842,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, if (!(flags & ZEND_PARSE_PARAMS_QUIET)) { zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW); - zend_internal_argument_count_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given", + zend_argument_count_error("%s%s%s() expects %s %d parameter%s, %d given", class_name, class_name[0] ? "::" : "", ZSTR_VAL(active_function->common.function_name), @@ -1073,20 +931,6 @@ ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /* } /* }}} */ -ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...) /* {{{ */ -{ - va_list va; - int retval; - int flags = ZEND_PARSE_PARAMS_THROW; - - va_start(va, type_spec); - retval = zend_parse_va_args(num_args, type_spec, &va, flags); - va_end(va); - - return retval; -} -/* }}} */ - ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */ { va_list va; @@ -1167,7 +1011,8 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this * because it may call __set from the uninitialized object otherwise. */ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ { - const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj); + zend_object *zobj = Z_OBJ_P(obj); + zend_object_write_property_t write_property = zobj->handlers->write_property; zend_class_entry *old_scope = EG(fake_scope); zend_string *key; zval *value; @@ -1175,10 +1020,7 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ EG(fake_scope) = Z_OBJCE_P(obj); ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) { if (key) { - zval member; - - ZVAL_STR(&member, key); - obj_ht->write_property(obj, &member, value, NULL); + write_property(zobj, key, value, NULL); } } ZEND_HASH_FOREACH_END(); EG(fake_scope) = old_scope; @@ -1224,7 +1066,7 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0)); } if (Z_TYPE_P(val) == IS_CONSTANT_AST) { - if (prop_info->type) { + if (ZEND_TYPE_IS_SET(prop_info->type)) { zval tmp; ZVAL_COPY(&tmp, val); @@ -1301,7 +1143,7 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti (property_info->flags & ZEND_ACC_STATIC) == 0) { zval *slot = OBJ_PROP(object, property_info->offset); - if (UNEXPECTED(property_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(property_info->type))) { zval tmp; ZVAL_COPY_VALUE(&tmp, prop); @@ -1690,7 +1532,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */ result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value); break; case IS_RESOURCE: - zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key)); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key)); result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value); break; case IS_FALSE: @@ -1706,7 +1548,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */ result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), value); break; default: - zend_error(E_WARNING, "Illegal offset type"); + zend_type_error("Illegal offset type"); result = NULL; } @@ -1801,11 +1643,11 @@ ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */ { - zval z_key; + zend_string *str; - ZVAL_STRINGL(&z_key, key, key_len); - Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, NULL); - zval_ptr_dtor(&z_key); + str = zend_string_init(key, key_len, 0); + Z_OBJ_HANDLER_P(arg, write_property)(Z_OBJ_P(arg), str, value, NULL); + zend_string_release_ex(str, 0); return SUCCESS; } /* }}} */ @@ -2204,21 +2046,17 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } else { internal_function->required_num_args = info->required_num_args; } - if (info->return_reference) { + if (ZEND_ARG_SEND_MODE(info)) { internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE; } - if (ptr->arg_info[ptr->num_args].is_variadic) { + if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) { internal_function->fn_flags |= ZEND_ACC_VARIADIC; /* Don't count the variadic argument */ internal_function->num_args--; } if (ZEND_TYPE_IS_SET(info->type)) { - if (ZEND_TYPE_IS_CLASS(info->type)) { - const char *type_name = (const char*)info->type; - - if (type_name[0] == '?') { - type_name++; - } + if (ZEND_TYPE_HAS_NAME(info->type)) { + const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type); if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) { zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name); } @@ -2298,29 +2136,19 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args); reg_function->common.arg_info = new_arg_info + 1; for (i = 0; i < num_args; i++) { - if (ZEND_TYPE_IS_CLASS(new_arg_info[i].type)) { - const char *class_name = (const char*)new_arg_info[i].type; - zend_bool allow_null = 0; - zend_string *str; - - if (class_name[0] == '?') { - class_name++; - allow_null = 1; - } - str = zend_string_init_interned(class_name, strlen(class_name), 1); - new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null); + if (ZEND_TYPE_HAS_CLASS(new_arg_info[i].type)) { + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(new_arg_info[i].type) + && "Only simple classes are currently supported"); + const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type); + ZEND_TYPE_SET_PTR(new_arg_info[i].type, + zend_string_init_interned(class_name, strlen(class_name), 1)); } } } if (scope) { - /* Look for ctor, dtor, clone - * If it's an old-style constructor, store it only if we don't have - * a constructor already. - */ - if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) { - ctor = reg_function; - } else if (zend_string_equals_literal(lowercase_name, "serialize")) { + /* Look for ctor, dtor, clone */ + if (zend_string_equals_literal(lowercase_name, "serialize")) { serialize_func = reg_function; } else if (zend_string_equals_literal(lowercase_name, "unserialize")) { unserialize_func = reg_function; @@ -2402,26 +2230,22 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio if (ctor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name)); } - ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (dtor) { dtor->common.fn_flags |= ZEND_ACC_DTOR; if (dtor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Destructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name)); } - dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (clone) { if (clone->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "%s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name)); } - clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__call) { if (__call->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__call->common.function_name)); } - __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__callstatic) { if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) { @@ -2433,31 +2257,26 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio if (__tostring->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__tostring->common.function_name)); } - __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__get) { if (__get->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__get->common.function_name)); } - __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__set) { if (__set->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__set->common.function_name)); } - __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__unset) { if (__unset->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__unset->common.function_name)); } - __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__isset) { if (__isset->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__isset->common.function_name)); } - __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__debugInfo) { if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) { @@ -2991,11 +2810,8 @@ static int zend_is_callable_check_class(zend_string *name, zend_class_entry *sco ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) { if (fcc->function_handler && - ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) || - fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || - fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) { - if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION && - fcc->function_handler->common.function_name) { + (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + if (fcc->function_handler->common.function_name) { zend_string_release_ex(fcc->function_handler->common.function_name, 0); } zend_free_trampoline(fcc->function_handler); @@ -3155,8 +2971,7 @@ get_function_via_handler: (!fcc->function_handler->common.scope || !instanceof_function(ce_org, fcc->function_handler->common.scope))) { if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { - if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION && - fcc->function_handler->common.function_name) { + if (fcc->function_handler->common.function_name) { zend_string_release_ex(fcc->function_handler->common.function_name, 0); } zend_free_trampoline(fcc->function_handler); @@ -3195,30 +3010,9 @@ get_function_via_handler: zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); } } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) { - int severity; - char *verb; - if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - severity = E_DEPRECATED; - verb = "should not"; - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - severity = E_ERROR; - verb = "cannot"; - } - if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) { - retval = 0; - } + retval = 0; if (error) { - zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb); - if (severity != E_DEPRECATED) { - retval = 0; - } - } else if (retval) { - if (severity == E_ERROR) { - zend_throw_error(NULL, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb); - } else { - zend_error(severity, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb); - } + zend_spprintf(error, 0, "non-static method %s::%s() cannot be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); } } if (retval @@ -3309,16 +3103,18 @@ try_again: zend_class_entry *calling_scope; zend_function *fptr; zend_object *object; - if (Z_OBJ_HANDLER_P(callable, get_closure) - && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &calling_scope, &fptr, &object) == SUCCESS) { - zend_class_entry *ce = Z_OBJCE_P(callable); + zend_object *zobj = Z_OBJ_P(callable); + + if (zobj->handlers->get_closure + && zobj->handlers->get_closure(zobj, &calling_scope, &fptr, &object, 1) == SUCCESS) { + zend_class_entry *ce = zobj->ce; zend_string *callable_name = zend_string_alloc( ZSTR_LEN(ce->name) + sizeof("::__invoke") - 1, 0); memcpy(ZSTR_VAL(callable_name), ZSTR_VAL(ce->name), ZSTR_LEN(ce->name)); memcpy(ZSTR_VAL(callable_name) + ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke")); return callable_name; } - return zval_get_string(callable); + return zval_get_string_func(callable); } case IS_REFERENCE: callable = Z_REFVAL_P(callable); @@ -3435,17 +3231,12 @@ check_func: } return 0; case IS_OBJECT: - if (Z_OBJ_HANDLER_P(callable, get_closure)) { - if (Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) { - fcc->called_scope = fcc->calling_scope; - if (fcc == &fcc_local) { - zend_release_fcall_info_cache(fcc); - } - return 1; - } else { - /* Discard exceptions thrown from Z_OBJ_HANDLER_P(callable, get_closure) */ - zend_clear_exception(); + if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == SUCCESS) { + fcc->called_scope = fcc->calling_scope; + if (fcc == &fcc_local) { + zend_release_fcall_info_cache(fcc); } + return 1; } if (error) *error = estrdup("no array or string given"); return 0; @@ -3478,7 +3269,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam { zend_fcall_info_cache fcc; - if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, &fcc, NULL)) { + if (zend_is_callable_ex(callable, NULL, 0, callable_name, &fcc, NULL)) { if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) { zval_ptr_dtor_str(callable); array_init(callable); @@ -3934,7 +3725,7 @@ ZEND_API int zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, ze ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */ { - return zend_declare_typed_property(ce, name, property, access_type, doc_comment, 0); + return zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0)); } /* }}} */ @@ -4112,13 +3903,11 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value) /* {{{ */ { - zval property; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STR(&property, name); - Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL); + Z_OBJ_HT_P(object)->write_property(Z_OBJ_P(object), name, value, NULL); EG(fake_scope) = old_scope; } @@ -4126,14 +3915,14 @@ ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zen ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value) /* {{{ */ { - zval property; + zend_string *property; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STRINGL(&property, name, name_length); - Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL); - zval_ptr_dtor(&property); + property = zend_string_init(name, name_length, 0); + Z_OBJ_HT_P(object)->write_property(Z_OBJ_P(object), property, value, NULL); + zend_string_release_ex(property, 0); EG(fake_scope) = old_scope; } @@ -4150,14 +3939,14 @@ ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, c ZEND_API void zend_unset_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length) /* {{{ */ { - zval property; + zend_string *property; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STRINGL(&property, name, name_length); - Z_OBJ_HT_P(object)->unset_property(object, &property, 0); - zval_ptr_dtor(&property); + property = zend_string_init(name, name_length, 0); + Z_OBJ_HT_P(object)->unset_property(Z_OBJ_P(object), property, 0); + zend_string_release_ex(property, 0); EG(fake_scope) = old_scope; } @@ -4241,7 +4030,7 @@ ZEND_API int zend_update_static_property_ex(zend_class_entry *scope, zend_string ZEND_ASSERT(!Z_ISREF_P(value)); Z_TRY_ADDREF_P(value); - if (prop_info->type) { + if (ZEND_TYPE_IS_SET(prop_info->type)) { ZVAL_COPY_VALUE(&tmp, value); if (!zend_verify_property_type(prop_info, &tmp, /* strict */ 0)) { Z_TRY_DELREF_P(value); @@ -4322,13 +4111,12 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zend_bool silent, zval *rv) /* {{{ */ { - zval property, *value; + zval *value; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STR(&property, name); - value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv); + value = Z_OBJ_HT_P(object)->read_property(Z_OBJ_P(object), name, silent?BP_VAR_IS:BP_VAR_R, NULL, rv); EG(fake_scope) = old_scope; return value; @@ -4499,7 +4287,7 @@ ZEND_API zend_bool zend_is_iterable(zval *iterable) /* {{{ */ case IS_ARRAY: return 1; case IS_OBJECT: - return instanceof_function(Z_OBJCE_P(iterable), zend_ce_traversable); + return zend_class_implements_interface(Z_OBJCE_P(iterable), zend_ce_traversable); default: return 0; } @@ -4516,7 +4304,7 @@ ZEND_API zend_bool zend_is_countable(zval *countable) /* {{{ */ return 1; } - return instanceof_function(Z_OBJCE_P(countable), zend_ce_countable); + return zend_class_implements_interface(Z_OBJCE_P(countable), zend_ce_countable); default: return 0; } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 2a3b582902..c822791850 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -27,6 +27,7 @@ #include "zend_operators.h" #include "zend_variables.h" #include "zend_execute.h" +#include "zend_type_info.h" BEGIN_EXTERN_C() @@ -95,34 +96,55 @@ typedef struct _zend_fcall_info_cache { #define ZEND_FE_END { NULL, NULL, NULL, 0, 0 } -#define ZEND_ARG_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 0}, -#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, pass_by_ref, 0}, -#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE(IS_ARRAY, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE(IS_CALLABLE, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE(type_hint, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 1 }, -#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE(type_hint, allow_null), pass_by_ref, 1 }, -#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 1 }, +#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \ + (((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0)) + +#define ZEND_ARG_INFO(pass_by_ref, name) \ + { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0))}, +#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \ + { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask) \ + { #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \ + { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, +#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, +#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) \ + { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CLASS_CONST(#class_name, allow_null), return_reference, 0 }, + { (const char*)(zend_uintptr_t)(required_num_args), \ + ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null) +#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \ + static const zend_internal_arg_info name[] = { \ + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, + +#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \ + static const zend_internal_arg_info name[] = { \ + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, + #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE(type, allow_null), return_reference, 0 }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null) #define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), 0, return_reference, 0 }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, #define ZEND_BEGIN_ARG_INFO(name, _unused) \ - ZEND_BEGIN_ARG_INFO_EX(name, 0, ZEND_RETURN_VALUE, -1) + ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1) #define ZEND_END_ARG_INFO() }; /* Name macros */ @@ -249,16 +271,18 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array); #define zend_parse_parameters_none() \ (EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : (zend_wrong_parameters_none_error(), FAILURE)) #define zend_parse_parameters_none_throw() \ - (EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : (zend_wrong_parameters_none_exception(), FAILURE)) + zend_parse_parameters_none() /* Parameter parsing API -- andrei */ +#define ZEND_PARSE_PARAMS_THROW 0 /* No longer used, zpp always uses exceptions */ #define ZEND_PARSE_PARAMS_QUIET (1<<1) -#define ZEND_PARSE_PARAMS_THROW (1<<2) ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...); ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...); -ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...); -ZEND_API char *zend_zval_type_name(const zval *arg); +/* NOTE: This must have at least one value in __VA_ARGS__ for the expression to be valid */ +#define zend_parse_parameters_throw(num_args, ...) \ + zend_parse_parameters(num_args, __VA_ARGS__) +ZEND_API const char *zend_zval_type_name(const zval *arg); ZEND_API zend_string *zend_zval_get_type(const zval *arg); ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...); @@ -298,11 +322,8 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void); #define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0) #define IS_CALLABLE_CHECK_NO_ACCESS (1<<1) -#define IS_CALLABLE_CHECK_IS_STATIC (1<<2) #define IS_CALLABLE_CHECK_SILENT (1<<3) -#define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC) - ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc); ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object); ZEND_API zend_string *zend_get_callable_name(zval *callable); @@ -360,7 +381,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, zend_bool silent); ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent); -ZEND_API char *zend_get_type_by_const(int type); +ZEND_API const char *zend_get_type_by_const(int type); #define ZEND_THIS (&EX(This)) @@ -477,7 +498,6 @@ ZEND_API extern const zend_fcall_info_cache empty_fcall_info_cache; * fci->param_count = 0; * fci->params = NULL; * The callable_name argument may be NULL. - * Set check_flags to IS_CALLABLE_STRICT for every new usage! */ ZEND_API int zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error); @@ -542,7 +562,7 @@ static zend_always_inline int zend_forbid_dynamic_call(const char *func_name) ZEND_ASSERT(ex != NULL && ex->func != NULL); if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) { - zend_error(E_WARNING, "Cannot call %s dynamically", func_name); + zend_throw_error(NULL, "Cannot call %s dynamically", func_name); return FAILURE; } @@ -636,26 +656,26 @@ END_EXTERN_C() #define RETVAL_FALSE ZVAL_FALSE(return_value) #define RETVAL_TRUE ZVAL_TRUE(return_value) -#define RETURN_BOOL(b) { RETVAL_BOOL(b); return; } -#define RETURN_NULL() { RETVAL_NULL(); return;} -#define RETURN_LONG(l) { RETVAL_LONG(l); return; } -#define RETURN_DOUBLE(d) { RETVAL_DOUBLE(d); return; } -#define RETURN_STR(s) { RETVAL_STR(s); return; } -#define RETURN_INTERNED_STR(s) { RETVAL_INTERNED_STR(s); return; } -#define RETURN_NEW_STR(s) { RETVAL_NEW_STR(s); return; } -#define RETURN_STR_COPY(s) { RETVAL_STR_COPY(s); return; } -#define RETURN_STRING(s) { RETVAL_STRING(s); return; } -#define RETURN_STRINGL(s, l) { RETVAL_STRINGL(s, l); return; } -#define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; } -#define RETURN_RES(r) { RETVAL_RES(r); return; } -#define RETURN_ARR(r) { RETVAL_ARR(r); return; } -#define RETURN_EMPTY_ARRAY() { RETVAL_EMPTY_ARRAY(); return; } -#define RETURN_OBJ(r) { RETVAL_OBJ(r); return; } -#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } -#define RETURN_FALSE { RETVAL_FALSE; return; } -#define RETURN_TRUE { RETVAL_TRUE; return; } - -#define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties((p)) : NULL))) +#define RETURN_BOOL(b) do { RETVAL_BOOL(b); return; } while (0) +#define RETURN_NULL() do { RETVAL_NULL(); return;} while (0) +#define RETURN_LONG(l) do { RETVAL_LONG(l); return; } while (0) +#define RETURN_DOUBLE(d) do { RETVAL_DOUBLE(d); return; } while (0) +#define RETURN_STR(s) do { RETVAL_STR(s); return; } while (0) +#define RETURN_INTERNED_STR(s) do { RETVAL_INTERNED_STR(s); return; } while (0) +#define RETURN_NEW_STR(s) do { RETVAL_NEW_STR(s); return; } while (0) +#define RETURN_STR_COPY(s) do { RETVAL_STR_COPY(s); return; } while (0) +#define RETURN_STRING(s) do { RETVAL_STRING(s); return; } while (0) +#define RETURN_STRINGL(s, l) do { RETVAL_STRINGL(s, l); return; } while (0) +#define RETURN_EMPTY_STRING() do { RETVAL_EMPTY_STRING(); return; } while (0) +#define RETURN_RES(r) do { RETVAL_RES(r); return; } while (0) +#define RETURN_ARR(r) do { RETVAL_ARR(r); return; } while (0) +#define RETURN_EMPTY_ARRAY() do { RETVAL_EMPTY_ARRAY(); return; } while (0) +#define RETURN_OBJ(r) do { RETVAL_OBJ(r); return; } while (0) +#define RETURN_ZVAL(zv, copy, dtor) do { RETVAL_ZVAL(zv, copy, dtor); return; } while (0) +#define RETURN_FALSE do { RETVAL_FALSE; return; } while (0) +#define RETURN_TRUE do { RETVAL_TRUE; return; } while (0) + +#define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties(Z_OBJ_P(p)) : NULL))) #define ZVAL_IS_NULL(z) (Z_TYPE_P(z) == IS_NULL) /* For compatibility */ @@ -1107,7 +1127,9 @@ static zend_always_inline zval *zend_try_array_init(zval *zv) _(Z_EXPECTED_RESOURCE, "resource") \ _(Z_EXPECTED_PATH, "a valid path") \ _(Z_EXPECTED_OBJECT, "object") \ - _(Z_EXPECTED_DOUBLE, "float") + _(Z_EXPECTED_DOUBLE, "float") \ + _(Z_EXPECTED_NUMBER, "int or float") \ + _(Z_EXPECTED_STRING_OR_ARRAY, "string or array") \ #define Z_EXPECTED_TYPE_ENUM(id, str) id, #define Z_EXPECTED_TYPE_STR(id, str) str, @@ -1118,16 +1140,10 @@ typedef enum _zend_expected_type { } zend_expected_type; ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void); -ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_num_args, int max_num_args); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, const char *name, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_deprecated(int num, char *error); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error); #define ZPP_ERROR_OK 0 #define ZPP_ERROR_FAILURE 1 @@ -1161,11 +1177,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha (UNEXPECTED(_num_args > _max_num_args) && \ EXPECTED(_max_num_args >= 0))) { \ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_parameters_count_exception(_min_num_args, _max_num_args); \ - } else { \ - zend_wrong_parameters_count_error(_min_num_args, _max_num_args); \ - } \ + zend_wrong_parameters_count_error(_min_num_args, _max_num_args); \ } \ _error_code = ZPP_ERROR_FAILURE; \ break; \ @@ -1187,23 +1199,11 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha if (UNEXPECTED(_error_code != ZPP_ERROR_OK)) { \ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \ if (_error_code == ZPP_ERROR_WRONG_CALLBACK) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_callback_exception(_i, _error); \ - } else { \ - zend_wrong_callback_error(_i, _error); \ - } \ + zend_wrong_callback_error(_i, _error); \ } else if (_error_code == ZPP_ERROR_WRONG_CLASS) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_parameter_class_exception(_i, _error, _arg); \ - } else { \ - zend_wrong_parameter_class_error(_i, _error, _arg); \ - } \ + zend_wrong_parameter_class_error(_i, _error, _arg); \ } else if (_error_code == ZPP_ERROR_WRONG_ARG) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_parameter_type_exception(_i, _expected_type, _arg); \ - } else { \ - zend_wrong_parameter_type_error(_i, _expected_type, _arg); \ - } \ + zend_wrong_parameter_type_error(_i, _expected_type, _arg); \ } \ } \ failure; \ @@ -1250,6 +1250,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha #define Z_PARAM_ARRAY(dest) \ Z_PARAM_ARRAY_EX(dest, 0, 0) +#define Z_PARAM_ARRAY_OR_NULL(dest) \ + Z_PARAM_ARRAY_EX(dest, 1, 0) + /* old "A" */ #define Z_PARAM_ARRAY_OR_OBJECT_EX2(dest, check_null, deref, separate) \ Z_PARAM_PROLOGUE(deref, separate); \ @@ -1316,14 +1319,11 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha if (!_error) { \ _expected_type = Z_EXPECTED_FUNC; \ _error_code = ZPP_ERROR_WRONG_ARG; \ - break; \ } else { \ _error_code = ZPP_ERROR_WRONG_CALLBACK; \ - break; \ } \ - } else if (UNEXPECTED(_error != NULL)) { \ - zend_wrong_callback_deprecated(_i, _error); \ - } + break; \ + } \ #define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, separate) \ Z_PARAM_FUNC_EX2(dest_fci, dest_fcc, check_null, separate, separate) @@ -1364,7 +1364,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha /* old "l" */ #define Z_PARAM_LONG_EX2(dest, is_null, check_null, deref, separate) \ Z_PARAM_PROLOGUE(deref, separate); \ - if (UNEXPECTED(!zend_parse_arg_long(_arg, &dest, &is_null, check_null, 0))) { \ + if (UNEXPECTED(!zend_parse_arg_long(_arg, &dest, &is_null, check_null))) { \ _expected_type = Z_EXPECTED_LONG; \ _error_code = ZPP_ERROR_WRONG_ARG; \ break; \ @@ -1376,20 +1376,23 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha #define Z_PARAM_LONG(dest) \ Z_PARAM_LONG_EX(dest, _dummy, 0, 0) -/* old "L" */ -#define Z_PARAM_STRICT_LONG_EX2(dest, is_null, check_null, deref, separate) \ - Z_PARAM_PROLOGUE(deref, separate); \ - if (UNEXPECTED(!zend_parse_arg_long(_arg, &dest, &is_null, check_null, 1))) { \ - _expected_type = Z_EXPECTED_LONG; \ - _error_code = ZPP_ERROR_WRONG_ARG; \ - break; \ - } +#define Z_PARAM_LONG_OR_NULL(dest, is_null) \ + Z_PARAM_LONG_EX(dest, is_null, 1, 0) + +/* no old equivalent */ +#define Z_PARAM_NUMBER_EX(dest, check_null) \ + Z_PARAM_PROLOGUE(0, 0); \ + if (UNEXPECTED(!zend_parse_arg_number(_arg, &dest, check_null))) { \ + _expected_type = Z_EXPECTED_NUMBER; \ + _error_code = ZPP_ERROR_WRONG_ARG; \ + break; \ + } -#define Z_PARAM_STRICT_LONG_EX(dest, is_null, check_null, separate) \ - Z_PARAM_STRICT_LONG_EX2(dest, is_null, check_null, separate, separate) +#define Z_PARAM_NUMBER_OR_NULL(dest) \ + Z_PARAM_NUMBER_EX(dest, 1) -#define Z_PARAM_STRICT_LONG(dest) \ - Z_PARAM_STRICT_LONG_EX(dest, _dummy, 0, 0) +#define Z_PARAM_NUMBER(dest) \ + Z_PARAM_NUMBER_EX(dest, 0) /* old "o" */ #define Z_PARAM_OBJECT_EX2(dest, check_null, deref, separate) \ @@ -1487,6 +1490,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha #define Z_PARAM_STRING(dest, dest_len) \ Z_PARAM_STRING_EX(dest, dest_len, 0, 0) +#define Z_PARAM_STRING_OR_NULL(dest, dest_len) \ + Z_PARAM_STRING_EX(dest, dest_len, 1, 0) + /* old "S" */ #define Z_PARAM_STR_EX2(dest, check_null, deref, separate) \ Z_PARAM_PROLOGUE(deref, separate); \ @@ -1513,14 +1519,6 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha #define Z_PARAM_ZVAL(dest) \ Z_PARAM_ZVAL_EX(dest, 0, 0) -/* old "z" (with dereference) */ -#define Z_PARAM_ZVAL_DEREF_EX(dest, check_null, separate) \ - Z_PARAM_PROLOGUE(1, separate); \ - zend_parse_arg_zval_deref(_arg, &dest, check_null); - -#define Z_PARAM_ZVAL_DEREF(dest) \ - Z_PARAM_ZVAL_DEREF_EX(dest, 0, 0) - /* old "+" and "*" */ #define Z_PARAM_VARIADIC_EX(spec, dest, dest_num, post_varargs) do { \ int _num_varargs = _num_args - _i - (post_varargs); \ @@ -1538,6 +1536,14 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha #define Z_PARAM_VARIADIC(spec, dest, dest_num) \ Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0) +#define Z_PARAM_STR_OR_ARRAY_HT(dest_str, dest_ht) \ + Z_PARAM_PROLOGUE(0, 0); \ + if (UNEXPECTED(!zend_parse_arg_str_or_array_ht(_arg, &dest_str, &dest_ht))) { \ + _expected_type = Z_EXPECTED_STRING_OR_ARRAY; \ + _error_code = ZPP_ERROR_WRONG_ARG; \ + break; \ + } + /* End of new parameter parsing API */ /* Inlined implementations shared by new and old parameter parsing APIs */ @@ -1547,12 +1553,11 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, zend_bool *dest); ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, zend_bool *dest); ZEND_API int ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest); ZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest); -ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_slow(zval *arg, zend_long *dest); -ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *dest); ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest); ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest); ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest); ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest); +ZEND_API int ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest); static zend_always_inline int zend_parse_arg_bool(zval *arg, zend_bool *dest, zend_bool *is_null, int check_null) { @@ -1572,7 +1577,7 @@ static zend_always_inline int zend_parse_arg_bool(zval *arg, zend_bool *dest, ze return 1; } -static zend_always_inline int zend_parse_arg_long(zval *arg, zend_long *dest, zend_bool *is_null, int check_null, int cap) +static zend_always_inline int zend_parse_arg_long(zval *arg, zend_long *dest, zend_bool *is_null, int check_null) { if (check_null) { *is_null = 0; @@ -1582,8 +1587,6 @@ static zend_always_inline int zend_parse_arg_long(zval *arg, zend_long *dest, ze } else if (check_null && Z_TYPE_P(arg) == IS_NULL) { *is_null = 1; *dest = 0; - } else if (cap) { - return zend_parse_arg_long_cap_slow(arg, dest); } else { return zend_parse_arg_long_slow(arg, dest); } @@ -1606,6 +1609,18 @@ static zend_always_inline int zend_parse_arg_double(zval *arg, double *dest, zen return 1; } +static zend_always_inline int zend_parse_arg_number(zval *arg, zval **dest, int check_null) +{ + if (EXPECTED(Z_TYPE_P(arg) == IS_LONG || Z_TYPE_P(arg) == IS_DOUBLE)) { + *dest = arg; + } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { + *dest = NULL; + } else { + return zend_parse_arg_number_slow(arg, dest); + } + return 1; +} + static zend_always_inline int zend_parse_arg_str(zval *arg, zend_string **dest, int check_null) { if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { @@ -1679,15 +1694,16 @@ static zend_always_inline int zend_parse_arg_array_ht(zval *arg, HashTable **des if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) { *dest = Z_ARRVAL_P(arg); } else if (or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(arg); if (separate - && Z_OBJ_P(arg)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(arg)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(arg)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(arg)->properties); + && zobj->properties + && UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); } - Z_OBJ_P(arg)->properties = zend_array_dup(Z_OBJ_P(arg)->properties); + zobj->properties = zend_array_dup(zobj->properties); } - *dest = Z_OBJ_HT_P(arg)->get_properties(arg); + *dest = zobj->handlers->get_properties(zobj); } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { *dest = NULL; } else { @@ -1746,6 +1762,22 @@ static zend_always_inline void zend_parse_arg_zval_deref(zval *arg, zval **dest, *dest = (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) ? NULL : arg; } +static zend_always_inline int zend_parse_arg_str_or_array_ht( + zval *arg, zend_string **dest_str, HashTable **dest_ht) +{ + if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { + *dest_str = Z_STR_P(arg); + *dest_ht = NULL; + } else if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) { + *dest_ht = Z_ARRVAL_P(arg); + *dest_str = NULL; + } else { + *dest_ht = NULL; + return zend_parse_arg_str_slow(arg, dest_str); + } + return 1; +} + END_EXTERN_C() #endif /* ZEND_API_H */ diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 21ccf85049..982bb03874 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -260,7 +260,7 @@ struct _zend_mm_heap { int peak_chunks_count; /* peak number of allocated chunks for current request */ int cached_chunks_count; /* number of cached chunks */ double avg_chunks_count; /* average number of chunks allocated per request */ - int last_chunks_delete_boundary; /* numer of chunks after last deletion */ + int last_chunks_delete_boundary; /* number of chunks after last deletion */ int last_chunks_delete_count; /* number of deletion over the last boundary */ #if ZEND_MM_CUSTOM union { diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index f17d4ba69a..a27ca9be0a 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -411,9 +411,9 @@ static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr) switch (Z_TYPE_P(offset)) { case IS_UNDEF: if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) { - zend_error(E_WARNING, + zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied"); - zval_ptr_dtor_nogc(expr); + return FAILURE; } break; case IS_STRING: @@ -436,11 +436,11 @@ static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr) zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr); break; case IS_RESOURCE: - zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset)); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset)); zend_hash_index_update(Z_ARRVAL_P(result), Z_RES_HANDLE_P(offset), expr); break; default: - zend_throw_error(NULL, "Illegal offset type"); + zend_type_error("Illegal offset type"); return FAILURE; } return SUCCESS; @@ -451,15 +451,16 @@ static int zend_ast_add_unpacked_element(zval *result, zval *expr) { HashTable *ht = Z_ARRVAL_P(expr); zval *val; zend_string *key; - + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { if (key) { zend_throw_error(NULL, "Cannot unpack array with string keys"); return FAILURE; } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) { - zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - break; + zend_throw_error(NULL, + "Cannot add element to the array as the next element is already occupied"); + return FAILURE; } Z_TRY_ADDREF_P(val); } @@ -910,8 +911,9 @@ ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) { * 160 left & * 170 non-associative == != === !== * 180 non-associative < <= > >= <=> + * 185 left . * 190 left << >> - * 200 left + - . + * 200 left + - * 210 left * / % * 220 right ! * 230 non-associative instanceof @@ -1312,6 +1314,23 @@ static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_d smart_str_appends(str, "}"); } +static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) { + if (ast->kind == ZEND_AST_TYPE_UNION) { + zend_ast_list *list = zend_ast_get_list(ast); + for (uint32_t i = 0; i < list->children; i++) { + if (i != 0) { + smart_str_appendc(str, '|'); + } + zend_ast_export_type(str, list->child[i], indent); + } + return; + } + if (ast->attr & ZEND_TYPE_NULLABLE) { + smart_str_appendc(str, '?'); + } + zend_ast_export_ns_name(str, ast, 0, indent); +} + #define BINARY_OP(_op, _p, _pl, _pr) do { \ op = _op; \ p = _p; \ @@ -1421,10 +1440,7 @@ tail_call: zend_ast_export_ex(str, decl->child[1], 0, indent); if (decl->child[3]) { smart_str_appends(str, ": "); - if (decl->child[3]->attr & ZEND_TYPE_NULLABLE) { - smart_str_appendc(str, '?'); - } - zend_ast_export_ns_name(str, decl->child[3], 0, indent); + zend_ast_export_type(str, decl->child[3], indent); } if (decl->child[2]) { if (decl->kind == ZEND_AST_ARROW_FUNC) { @@ -1514,11 +1530,7 @@ simple_list: } if (type_ast) { - if (type_ast->attr & ZEND_TYPE_NULLABLE) { - smart_str_appendc(str, '?'); - } - zend_ast_export_ns_name( - str, type_ast, 0, indent); + zend_ast_export_type(str, type_ast, indent); smart_str_appendc(str, ' '); } @@ -1738,8 +1750,7 @@ simple_list: case ZEND_MOD: BINARY_OP(" % ", 210, 210, 211); case ZEND_SL: BINARY_OP(" << ", 190, 190, 191); case ZEND_SR: BINARY_OP(" >> ", 190, 190, 191); - case ZEND_PARENTHESIZED_CONCAT: /* fallthrough */ - case ZEND_CONCAT: BINARY_OP(" . ", 200, 200, 201); + case ZEND_CONCAT: BINARY_OP(" . ", 185, 185, 186); case ZEND_BW_OR: BINARY_OP(" | ", 140, 140, 141); case ZEND_BW_AND: BINARY_OP(" & ", 160, 160, 161); case ZEND_BW_XOR: BINARY_OP(" ^ ", 150, 150, 151); @@ -1989,10 +2000,7 @@ simple_list: break; case ZEND_AST_PARAM: if (ast->child[0]) { - if (ast->child[0]->attr & ZEND_TYPE_NULLABLE) { - smart_str_appendc(str, '?'); - } - zend_ast_export_ns_name(str, ast->child[0], 0, indent); + zend_ast_export_type(str, ast->child[0], indent); smart_str_appendc(str, ' '); } if (ast->attr & ZEND_PARAM_REF) { diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index fd6dd1677a..5b8aae6f96 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -61,6 +61,7 @@ enum _zend_ast_kind { ZEND_AST_NAME_LIST, ZEND_AST_TRAIT_ADAPTATIONS, ZEND_AST_USE, + ZEND_AST_TYPE_UNION, /* 0 child nodes */ ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT, diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index d3bf032c10..a369b1eab7 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -37,7 +37,6 @@ static ZEND_FUNCTION(strcmp); static ZEND_FUNCTION(strncmp); static ZEND_FUNCTION(strcasecmp); static ZEND_FUNCTION(strncasecmp); -static ZEND_FUNCTION(each); static ZEND_FUNCTION(error_reporting); static ZEND_FUNCTION(define); static ZEND_FUNCTION(defined); @@ -68,7 +67,6 @@ static ZEND_FUNCTION(get_declared_traits); static ZEND_FUNCTION(get_declared_interfaces); static ZEND_FUNCTION(get_defined_functions); static ZEND_FUNCTION(get_defined_vars); -static ZEND_FUNCTION(create_function); static ZEND_FUNCTION(get_resource_type); static ZEND_FUNCTION(get_resources); static ZEND_FUNCTION(get_loaded_extensions); @@ -87,219 +85,69 @@ static ZEND_FUNCTION(gc_enable); static ZEND_FUNCTION(gc_disable); static ZEND_FUNCTION(gc_status); -/* {{{ arginfo */ -ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1) - ZEND_ARG_INFO(0, arg_num) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_strlen, 0, 0, 1) - ZEND_ARG_INFO(0, str) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_strcmp, 0, 0, 2) - ZEND_ARG_INFO(0, str1) - ZEND_ARG_INFO(0, str2) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3) - ZEND_ARG_INFO(0, str1) - ZEND_ARG_INFO(0, str2) - ZEND_ARG_INFO(0, len) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1) - ZEND_ARG_INFO(1, arr) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0) - ZEND_ARG_INFO(0, new_error_level) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_define, 0, 0, 2) - ZEND_ARG_INFO(0, constant_name) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, case_insensitive) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_defined, 0, 0, 1) - ZEND_ARG_INFO(0, constant_name) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class, 0, 0, 0) - ZEND_ARG_INFO(0, object) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2) - ZEND_ARG_INFO(0, object) - ZEND_ARG_INFO(0, class_name) - ZEND_ARG_INFO(0, allow_string) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1) - ZEND_ARG_INFO(0, class_name) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_object_vars, 0, 0, 1) - ZEND_ARG_INFO(0, obj) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_mangled_object_vars, 0, 0, 1) - ZEND_ARG_INFO(0, obj) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_methods, 0, 0, 1) - ZEND_ARG_INFO(0, class) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_method_exists, 0, 0, 2) - ZEND_ARG_INFO(0, object) - ZEND_ARG_INFO(0, method) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_property_exists, 0, 0, 2) - ZEND_ARG_INFO(0, object_or_class) - ZEND_ARG_INFO(0, property_name) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1) - ZEND_ARG_INFO(0, classname) - ZEND_ARG_INFO(0, autoload) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_trait_exists, 0, 0, 1) - ZEND_ARG_INFO(0, traitname) - ZEND_ARG_INFO(0, autoload) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1) - ZEND_ARG_INFO(0, function_name) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2) - ZEND_ARG_INFO(0, user_class_name) - ZEND_ARG_INFO(0, alias_name) - ZEND_ARG_INFO(0, autoload) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1) - ZEND_ARG_INFO(0, message) - ZEND_ARG_INFO(0, error_type) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1) - ZEND_ARG_INFO(0, error_handler) - ZEND_ARG_INFO(0, error_types) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1) - ZEND_ARG_INFO(0, exception_handler) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_functions, 0, 0, 0) - ZEND_ARG_INFO(0, exclude_disabled) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2) - ZEND_ARG_INFO(0, args) - ZEND_ARG_INFO(0, code) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1) - ZEND_ARG_INFO(0, res) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resources, 0, 0, 0) - ZEND_ARG_INFO(0, type) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0) - ZEND_ARG_INFO(0, zend_extensions) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0) - ZEND_ARG_INFO(0, categorize) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0) - ZEND_ARG_INFO(0, options) - ZEND_ARG_INFO(0, limit) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_print_backtrace, 0, 0, 0) - ZEND_ARG_INFO(0, options) - ZEND_ARG_INFO(0, limit) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1) - ZEND_ARG_INFO(0, extension_name) -ZEND_END_ARG_INFO() +#include "zend_builtin_functions_arginfo.h" /* }}} */ static const zend_function_entry builtin_functions[] = { /* {{{ */ - ZEND_FE(zend_version, arginfo_zend__void) - ZEND_FE(func_num_args, arginfo_zend__void) + ZEND_FE(zend_version, arginfo_zend_version) + ZEND_FE(func_num_args, arginfo_func_num_args) ZEND_FE(func_get_arg, arginfo_func_get_arg) - ZEND_FE(func_get_args, arginfo_zend__void) + ZEND_FE(func_get_args, arginfo_func_get_args) ZEND_FE(strlen, arginfo_strlen) ZEND_FE(strcmp, arginfo_strcmp) ZEND_FE(strncmp, arginfo_strncmp) ZEND_FE(strcasecmp, arginfo_strcmp) ZEND_FE(strncasecmp, arginfo_strncmp) - ZEND_FE(each, arginfo_each) ZEND_FE(error_reporting, arginfo_error_reporting) ZEND_FE(define, arginfo_define) ZEND_FE(defined, arginfo_defined) ZEND_FE(get_class, arginfo_get_class) - ZEND_FE(get_called_class, arginfo_zend__void) - ZEND_FE(get_parent_class, arginfo_get_class) + ZEND_FE(get_called_class, arginfo_get_called_class) + ZEND_FE(get_parent_class, arginfo_get_parent_class) ZEND_FE(method_exists, arginfo_method_exists) ZEND_FE(property_exists, arginfo_property_exists) ZEND_FE(class_exists, arginfo_class_exists) - ZEND_FE(interface_exists, arginfo_class_exists) + ZEND_FE(interface_exists, arginfo_interface_exists) ZEND_FE(trait_exists, arginfo_trait_exists) ZEND_FE(function_exists, arginfo_function_exists) ZEND_FE(class_alias, arginfo_class_alias) - ZEND_FE(get_included_files, arginfo_zend__void) - ZEND_FALIAS(get_required_files, get_included_files, arginfo_zend__void) + ZEND_FE(get_included_files, arginfo_get_included_files) + ZEND_FALIAS(get_required_files, get_included_files, arginfo_get_required_files) ZEND_FE(is_subclass_of, arginfo_is_subclass_of) - ZEND_FE(is_a, arginfo_is_subclass_of) + ZEND_FE(is_a, arginfo_is_a) ZEND_FE(get_class_vars, arginfo_get_class_vars) ZEND_FE(get_object_vars, arginfo_get_object_vars) ZEND_FE(get_mangled_object_vars, arginfo_get_mangled_object_vars) ZEND_FE(get_class_methods, arginfo_get_class_methods) ZEND_FE(trigger_error, arginfo_trigger_error) - ZEND_FALIAS(user_error, trigger_error, arginfo_trigger_error) + ZEND_FALIAS(user_error, trigger_error, arginfo_user_error) ZEND_FE(set_error_handler, arginfo_set_error_handler) - ZEND_FE(restore_error_handler, arginfo_zend__void) + ZEND_FE(restore_error_handler, arginfo_restore_error_handler) ZEND_FE(set_exception_handler, arginfo_set_exception_handler) - ZEND_FE(restore_exception_handler, arginfo_zend__void) - ZEND_FE(get_declared_classes, arginfo_zend__void) - ZEND_FE(get_declared_traits, arginfo_zend__void) - ZEND_FE(get_declared_interfaces, arginfo_zend__void) + ZEND_FE(restore_exception_handler, arginfo_restore_exception_handler) + ZEND_FE(get_declared_classes, arginfo_get_declared_classes) + ZEND_FE(get_declared_traits, arginfo_get_declared_traits) + ZEND_FE(get_declared_interfaces, arginfo_get_declared_interfaces) ZEND_FE(get_defined_functions, arginfo_get_defined_functions) - ZEND_FE(get_defined_vars, arginfo_zend__void) - ZEND_DEP_FE(create_function, arginfo_create_function) + ZEND_FE(get_defined_vars, arginfo_get_defined_vars) ZEND_FE(get_resource_type, arginfo_get_resource_type) ZEND_FE(get_resources, arginfo_get_resources) ZEND_FE(get_loaded_extensions, arginfo_get_loaded_extensions) ZEND_FE(extension_loaded, arginfo_extension_loaded) - ZEND_FE(get_extension_funcs, arginfo_extension_loaded) + ZEND_FE(get_extension_funcs, arginfo_get_extension_funcs) ZEND_FE(get_defined_constants, arginfo_get_defined_constants) ZEND_FE(debug_backtrace, arginfo_debug_backtrace) ZEND_FE(debug_print_backtrace, arginfo_debug_print_backtrace) #if ZEND_DEBUG && defined(ZTS) - ZEND_FE(zend_thread_id, NULL) + ZEND_FE(zend_thread_id, arginfo_zend_thread_id) #endif - ZEND_FE(gc_mem_caches, arginfo_zend__void) - ZEND_FE(gc_collect_cycles, arginfo_zend__void) - ZEND_FE(gc_enabled, arginfo_zend__void) - ZEND_FE(gc_enable, arginfo_zend__void) - ZEND_FE(gc_disable, arginfo_zend__void) - ZEND_FE(gc_status, arginfo_zend__void) + ZEND_FE(gc_mem_caches, arginfo_gc_mem_caches) + ZEND_FE(gc_collect_cycles, arginfo_gc_collect_cycles) + ZEND_FE(gc_enabled, arginfo_gc_enabled) + ZEND_FE(gc_enable, arginfo_gc_enable) + ZEND_FE(gc_disable, arginfo_gc_disable) + ZEND_FE(gc_status, arginfo_gc_status) ZEND_FE_END }; /* }}} */ @@ -668,66 +516,6 @@ ZEND_FUNCTION(strncasecmp) } /* }}} */ -/* {{{ proto mixed each(array &arr) - Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element, or false if there is no element at this place */ -ZEND_FUNCTION(each) -{ - zval *array, *entry, tmp; - zend_ulong num_key; - HashTable *target_hash; - zend_string *key; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/", &array) == FAILURE) { - return; - } - - if (!EG(each_deprecation_thrown)) { - zend_error(E_DEPRECATED, "The each() function is deprecated. This message will be suppressed on further calls"); - EG(each_deprecation_thrown) = 1; - } - - target_hash = HASH_OF(array); - if (!target_hash) { - zend_error(E_WARNING,"Variable passed to each() is not an array or object"); - return; - } - while (1) { - entry = zend_hash_get_current_data(target_hash); - if (!entry) { - RETURN_FALSE; - } else if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - if (Z_TYPE_P(entry) == IS_UNDEF) { - zend_hash_move_forward(target_hash); - continue; - } - } - break; - } - array_init_size(return_value, 4); - zend_hash_real_init_mixed(Z_ARRVAL_P(return_value)); - - /* add value elements */ - ZVAL_DEREF(entry); - if (Z_REFCOUNTED_P(entry)) { - GC_ADDREF_EX(Z_COUNTED_P(entry), 2); - } - zend_hash_index_add_new(Z_ARRVAL_P(return_value), 1, entry); - zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_VALUE), entry); - - /* add the key elements */ - if (zend_hash_get_current_key(target_hash, &key, &num_key) == HASH_KEY_IS_STRING) { - ZVAL_STR_COPY(&tmp, key); - Z_TRY_ADDREF(tmp); - } else { - ZVAL_LONG(&tmp, num_key); - } - zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp); - zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_KEY), &tmp); - zend_hash_move_forward(target_hash); -} -/* }}} */ - /* {{{ proto int error_reporting([int new_error_level]) Return the current error_reporting level, and if an argument was passed - change to the new level */ ZEND_FUNCTION(error_reporting) @@ -851,7 +639,6 @@ ZEND_FUNCTION(define) zend_string *name; zval *val, val_free; zend_bool non_cs = 0; - int case_sensitive = CONST_CS; zend_constant c; ZEND_PARSE_PARAMETERS_START(2, 3) @@ -861,18 +648,19 @@ ZEND_FUNCTION(define) Z_PARAM_BOOL(non_cs) ZEND_PARSE_PARAMETERS_END(); - if (non_cs) { - case_sensitive = 0; - } - if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) { zend_error(E_WARNING, "Class constants cannot be defined or redefined"); RETURN_FALSE; } + if (non_cs) { + zend_error(E_WARNING, + "define(): Declaration of case-insensitive constants is no longer supported"); + RETURN_FALSE; + } + ZVAL_UNDEF(&val_free); -repeat: switch (Z_TYPE_P(val)) { case IS_LONG: case IS_DOUBLE: @@ -893,17 +681,10 @@ repeat: } break; case IS_OBJECT: - if (Z_TYPE(val_free) == IS_UNDEF) { - if (Z_OBJ_HT_P(val)->get) { - zval rv; - val = Z_OBJ_HT_P(val)->get(val, &rv); - ZVAL_COPY_VALUE(&val_free, val); - goto repeat; - } else if (Z_OBJ_HT_P(val)->cast_object) { - if (Z_OBJ_HT_P(val)->cast_object(val, &val_free, IS_STRING) == SUCCESS) { - val = &val_free; - break; - } + if (Z_OBJ_HT_P(val)->cast_object) { + if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) { + val = &val_free; + break; } } /* no break */ @@ -917,13 +698,8 @@ repeat: zval_ptr_dtor(&val_free); register_constant: - if (non_cs) { - zend_error(E_DEPRECATED, - "define(): Declaration of case-insensitive constants is deprecated"); - } - /* non persistent */ - ZEND_CONSTANT_SET_FLAGS(&c, case_sensitive, PHP_USER_CONSTANT); + ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, PHP_USER_CONSTANT); c.name = zend_string_copy(name); if (zend_register_constant(&c) == SUCCESS) { RETURN_TRUE; @@ -944,7 +720,7 @@ ZEND_FUNCTION(defined) Z_PARAM_STR(name) ZEND_PARSE_PARAMETERS_END(); - if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT | ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) { + if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) { RETURN_TRUE; } else { RETURN_FALSE; @@ -959,7 +735,7 @@ ZEND_FUNCTION(get_class) zval *obj = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o", &obj) == FAILURE) { - RETURN_FALSE; + return; } if (!obj) { @@ -1192,13 +968,12 @@ ZEND_FUNCTION(get_object_vars) Z_PARAM_OBJECT(obj) ZEND_PARSE_PARAMETERS_END(); - properties = Z_OBJ_HT_P(obj)->get_properties(obj); + zobj = Z_OBJ_P(obj); + properties = zobj->handlers->get_properties(zobj); if (properties == NULL) { - RETURN_FALSE; + RETURN_EMPTY_ARRAY(); } - zobj = Z_OBJ_P(obj); - if (!zobj->ce->default_properties_count && properties == zobj->properties && !GC_IS_RECURSIVE(properties)) { /* fast copy */ if (EXPECTED(zobj->handlers == &std_object_handlers)) { @@ -1260,7 +1035,7 @@ ZEND_FUNCTION(get_mangled_object_vars) Z_PARAM_OBJECT(obj) ZEND_PARSE_PARAMETERS_END(); - properties = Z_OBJ_HT_P(obj)->get_properties(obj); + properties = Z_OBJ_HT_P(obj)->get_properties(Z_OBJ_P(obj)); if (!properties) { ZVAL_EMPTY_ARRAY(return_value); return; @@ -1408,7 +1183,6 @@ ZEND_FUNCTION(property_exists) zend_string *property; zend_class_entry *ce; zend_property_info *property_info; - zval property_z; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) { return; @@ -1437,10 +1211,8 @@ ZEND_FUNCTION(property_exists) RETURN_TRUE; } - ZVAL_STR(&property_z, property); - if (Z_TYPE_P(object) == IS_OBJECT && - Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) { + Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, 2, NULL)) { RETURN_TRUE; } RETURN_FALSE; @@ -1593,7 +1365,7 @@ ZEND_FUNCTION(get_included_files) } /* }}} */ -/* {{{ proto void trigger_error(string message [, int error_type]) +/* {{{ proto bool trigger_error(string message [, int error_type]) Generates a user-level error/warning/notice message */ ZEND_FUNCTION(trigger_error) { @@ -1849,6 +1621,9 @@ ZEND_FUNCTION(get_defined_functions) ZEND_FUNCTION(get_defined_vars) { zend_array *symbol_table; + + ZEND_PARSE_PARAMETERS_NONE(); + if (zend_forbid_dynamic_call("get_defined_vars()") == FAILURE) { return; } @@ -1862,81 +1637,11 @@ ZEND_FUNCTION(get_defined_vars) } /* }}} */ -#define LAMBDA_TEMP_FUNCNAME "__lambda_func" -/* {{{ proto string create_function(string args, string code) - Creates an anonymous function, and returns its name (funny, eh?) */ -ZEND_FUNCTION(create_function) -{ - zend_string *function_name; - char *eval_code, *function_args, *function_code; - size_t eval_code_length, function_args_len, function_code_len; - int retval; - char *eval_name; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) { - return; - } - - eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME) - +function_args_len - +2 /* for the args parentheses */ - +2 /* for the curly braces */ - +function_code_len); - - eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1; - memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length); - - memcpy(eval_code + eval_code_length, function_args, function_args_len); - eval_code_length += function_args_len; - - eval_code[eval_code_length++] = ')'; - eval_code[eval_code_length++] = '{'; - - memcpy(eval_code + eval_code_length, function_code, function_code_len); - eval_code_length += function_code_len; - - eval_code[eval_code_length++] = '}'; - eval_code[eval_code_length] = '\0'; - - eval_name = zend_make_compiled_string_description("runtime-created function"); - retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name); - efree(eval_code); - efree(eval_name); - - if (retval==SUCCESS) { - zend_op_array *func; - HashTable *static_variables; - - func = zend_hash_str_find_ptr(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - if (!func) { - zend_error_noreturn(E_CORE_ERROR, "Unexpected inconsistency in create_function()"); - RETURN_FALSE; - } - if (func->refcount) { - (*func->refcount)++; - } - static_variables = func->static_variables; - func->static_variables = NULL; - zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - func->static_variables = static_variables; - - function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0); - ZSTR_VAL(function_name)[0] = '\0'; - - do { - ZSTR_LEN(function_name) = snprintf(ZSTR_VAL(function_name) + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1; - } while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL); - RETURN_NEW_STR(function_name); - } else { - zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - RETURN_FALSE; - } -} -/* }}} */ - #if ZEND_DEBUG && defined(ZTS) ZEND_FUNCTION(zend_thread_id) { + ZEND_PARSE_PARAMETERS_NONE(); + RETURN_LONG((zend_long)tsrm_thread_id()); } #endif diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php new file mode 100644 index 0000000000..57c3f5830c --- /dev/null +++ b/Zend/zend_builtin_functions.stub.php @@ -0,0 +1,116 @@ +<?php + +function zend_version(): string {} + +function func_num_args(): int {} + +/** @return mixed */ +function func_get_arg(int $arg_num) {} + +function func_get_args(): array|false {} + +function strlen(string $str): int {} + +function strcmp(string $str1, string $str2): int {} + +function strncmp(string $str1, string $str2, int $len): int|false {} + +function error_reporting($new_error_level = UNKNOWN): int {} + +function define(string $constant_name, $value, bool $case_insensitive = false): bool {} + +function defined(string $constant_name): bool {} + +function get_class(object $object = UNKNOWN): string|false {} + +function get_called_class(): string|false {} + +function get_parent_class($object = UNKNOWN): string|false {} + +function is_subclass_of($object, string $class_name, bool $allow_string = true): bool {} + +function is_a($object, string $class_name, bool $allow_string = false): bool {} + +function get_class_vars(string $class_name): array|false {} + +function get_object_vars(object $obj): array {} + +function get_mangled_object_vars(object $obj): array {} + +function get_class_methods($class): ?array {} + +function method_exists($object_or_class, string $method): bool {} + +function property_exists($object_or_class, string $property_name): ?bool {} + +function class_exists(string $classname, bool $autoload = true): bool {} + +function interface_exists(string $classname, bool $autoload = true): bool {} + +function trait_exists(string $traitname, bool $autoload = true): bool {} + +function function_exists(string $function_name): bool {} + +function class_alias(string $user_class_name, string $alias_name, bool $autoload = true): bool {} + +function get_included_files(): array {} + +/** @alias get_included_files */ +function get_required_files(): array {} + +function trigger_error(string $message, int $error_type = E_USER_NOTICE): bool {} + +/** @alias trigger_error */ +function user_error(string $message, int $error_type = E_USER_NOTICE): bool {} + +/** @return mixed */ +function set_error_handler($error_handler, int $error_types = E_ALL) {} + +function restore_error_handler(): bool {} + +/** @return mixed */ +function set_exception_handler($exception_handler) {} + +function restore_exception_handler(): bool {} + +function get_declared_classes(): array {} + +function get_declared_traits(): array {} + +function get_declared_interfaces(): array {} + +function get_defined_functions(bool $exclude_disabled = false): array {} + +function get_defined_vars(): ?array {} + +function get_resource_type($res): string {} + +function get_resources(string $type = UNKNOWN): array {} + +function get_loaded_extensions(bool $zend_extensions = false): array {} + +function get_defined_constants(bool $categorize = false): array {} + +function debug_backtrace(int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit = 0): array {} + +function debug_print_backtrace(int $options = 0, int $limit = 0): void {} + +function extension_loaded(string $extension_name): bool {} + +function get_extension_funcs(string $extension_name): array|false {} + +#if ZEND_DEBUG && defined(ZTS) +function zend_thread_id(): int {} +#endif + +function gc_mem_caches(): int {} + +function gc_collect_cycles(): int {} + +function gc_enabled(): bool {} + +function gc_enable(): void {} + +function gc_disable(): void {} + +function gc_status(): array {} diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h new file mode 100644 index 0000000000..bfe5b82a8a --- /dev/null +++ b/Zend/zend_builtin_functions_arginfo.h @@ -0,0 +1,199 @@ +/* This is a generated file, edit the .stub.php file instead. */ + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_func_num_args, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, arg_num, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_func_get_args, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_strlen, 0, 1, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_strcmp, 0, 2, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, str1, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, str2, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strncmp, 0, 3, MAY_BE_LONG|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, str1, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, str2, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, len, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_error_reporting, 0, 0, IS_LONG, 0) + ZEND_ARG_INFO(0, new_error_level) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_define, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, constant_name, IS_STRING, 0) + ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_INFO(0, case_insensitive, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_defined, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, constant_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_class, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_called_class, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_parent_class, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_INFO(0, object) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_is_subclass_of, 0, 2, _IS_BOOL, 0) + ZEND_ARG_INFO(0, object) + ZEND_ARG_TYPE_INFO(0, class_name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, allow_string, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +#define arginfo_is_a arginfo_is_subclass_of + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_class_vars, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, class_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_object_vars, 0, 1, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, obj, IS_OBJECT, 0) +ZEND_END_ARG_INFO() + +#define arginfo_get_mangled_object_vars arginfo_get_object_vars + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_class_methods, 0, 1, IS_ARRAY, 1) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_method_exists, 0, 2, _IS_BOOL, 0) + ZEND_ARG_INFO(0, object_or_class) + ZEND_ARG_TYPE_INFO(0, method, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_property_exists, 0, 2, _IS_BOOL, 1) + ZEND_ARG_INFO(0, object_or_class) + ZEND_ARG_TYPE_INFO(0, property_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_exists, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, classname, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, autoload, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +#define arginfo_interface_exists arginfo_class_exists + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_trait_exists, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, traitname, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, autoload, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_function_exists, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, function_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_alias, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, user_class_name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, alias_name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, autoload, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_included_files, 0, 0, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +#define arginfo_get_required_files arginfo_get_included_files + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_trigger_error, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, error_type, IS_LONG, 0) +ZEND_END_ARG_INFO() + +#define arginfo_user_error arginfo_trigger_error + +ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1) + ZEND_ARG_INFO(0, error_handler) + ZEND_ARG_TYPE_INFO(0, error_types, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1) + ZEND_ARG_INFO(0, exception_handler) +ZEND_END_ARG_INFO() + +#define arginfo_restore_exception_handler arginfo_restore_error_handler + +#define arginfo_get_declared_classes arginfo_get_included_files + +#define arginfo_get_declared_traits arginfo_get_included_files + +#define arginfo_get_declared_interfaces arginfo_get_included_files + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_defined_functions, 0, 0, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, exclude_disabled, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_defined_vars, 0, 0, IS_ARRAY, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_resource_type, 0, 1, IS_STRING, 0) + ZEND_ARG_INFO(0, res) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_resources, 0, 0, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, type, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_loaded_extensions, 0, 0, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, zend_extensions, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_defined_constants, 0, 0, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, categorize, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_debug_backtrace, 0, 0, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, options, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, limit, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_debug_print_backtrace, 0, 0, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, options, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, limit, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_extension_loaded, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, extension_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_extension_funcs, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, extension_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#if ZEND_DEBUG && defined(ZTS) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_thread_id, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() +#endif + +#define arginfo_gc_mem_caches arginfo_func_num_args + +#define arginfo_gc_collect_cycles arginfo_func_num_args + +#define arginfo_gc_enabled arginfo_restore_error_handler + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gc_enable, 0, 0, IS_VOID, 0) +ZEND_END_ARG_INFO() + +#define arginfo_gc_disable arginfo_gc_enable + +#define arginfo_gc_status arginfo_get_included_files diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 92f1398d84..b1bebaded4 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -26,6 +26,7 @@ #include "zend_objects.h" #include "zend_objects_API.h" #include "zend_globals.h" +#include "zend_closures_arginfo.h" #define ZEND_CLOSURE_PRINT_NAME "Closure object" @@ -84,16 +85,12 @@ static zend_bool zend_valid_closure_binding( } } else if (is_fake_closure && func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { - if (func->type == ZEND_INTERNAL_FUNCTION) { - zend_error(E_WARNING, "Cannot unbind $this of internal method"); - return 0; - } else { - zend_error(E_DEPRECATED, "Unbinding $this of a method is deprecated"); - } + zend_error(E_WARNING, "Cannot unbind $this of method"); + return 0; } else if (!is_fake_closure && !Z_ISUNDEF(closure->this_ptr) && (func->common.fn_flags & ZEND_ACC_USES_THIS)) { - // TODO: Only deprecate if it had $this *originally*? - zend_error(E_DEPRECATED, "Unbinding $this of closure is deprecated"); + zend_error(E_WARNING, "Cannot unbind $this of closure using $this"); + return 0; } if (scope && scope != func->common.scope && scope->type == ZEND_INTERNAL_CLASS) { @@ -349,7 +346,7 @@ ZEND_METHOD(Closure, fromCallable) success = zend_create_closure_from_callable(return_value, callable, &error); EG(current_execute_data) = execute_data; - if (success == FAILURE || error) { + if (success == FAILURE) { if (error) { zend_type_error("Failed to create closure from callable: %s", error); efree(error); @@ -367,9 +364,10 @@ static ZEND_COLD zend_function *zend_closure_get_constructor(zend_object *object } /* }}} */ -static int zend_closure_compare_objects(zval *o1, zval *o2) /* {{{ */ +static int zend_closure_compare(zval *o1, zval *o2) /* {{{ */ { - return (Z_OBJ_P(o1) != Z_OBJ_P(o2)); + ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2); + return Z_OBJ_P(o1) != Z_OBJ_P(o2); } /* }}} */ @@ -425,28 +423,28 @@ static zend_function *zend_closure_get_method(zend_object **object, zend_string } /* }}} */ -static ZEND_COLD zval *zend_closure_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ +static ZEND_COLD zval *zend_closure_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); return &EG(uninitialized_zval); } /* }}} */ -static ZEND_COLD zval *zend_closure_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ +static ZEND_COLD zval *zend_closure_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); return &EG(error_zval); } /* }}} */ -static ZEND_COLD zval *zend_closure_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +static ZEND_COLD zval *zend_closure_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); return NULL; } /* }}} */ -static ZEND_COLD int zend_closure_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */ +static ZEND_COLD int zend_closure_has_property(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot) /* {{{ */ { if (has_set_exists != ZEND_PROPERTY_EXISTS) { ZEND_CLOSURE_PROPERTY_ERROR(); @@ -455,7 +453,7 @@ static ZEND_COLD int zend_closure_has_property(zval *object, zval *member, int h } /* }}} */ -static ZEND_COLD void zend_closure_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ +static ZEND_COLD void zend_closure_unset_property(zend_object *object, zend_string *member, void **cache_slot) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); } @@ -491,9 +489,9 @@ static zend_object *zend_closure_new(zend_class_entry *class_type) /* {{{ */ } /* }}} */ -static zend_object *zend_closure_clone(zval *zobject) /* {{{ */ +static zend_object *zend_closure_clone(zend_object *zobject) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(zobject); + zend_closure *closure = (zend_closure *)zobject; zval result; zend_create_closure(&result, &closure->func, @@ -502,9 +500,9 @@ static zend_object *zend_closure_clone(zval *zobject) /* {{{ */ } /* }}} */ -int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(obj); + zend_closure *closure = (zend_closure *)obj; *fptr_ptr = &closure->func; *ce_ptr = closure->called_scope; @@ -518,9 +516,9 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function } /* }}} */ -static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{ */ +static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(object); + zend_closure *closure = (zend_closure *)object; zval val; struct _zend_arg_info *arg_info = closure->func.common.arg_info; HashTable *debug_info; @@ -559,16 +557,16 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{ if (arg_info->name) { if (zstr_args) { name = zend_strpprintf(0, "%s$%s", - arg_info->pass_by_reference ? "&" : "", + ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", ZSTR_VAL(arg_info->name)); } else { name = zend_strpprintf(0, "%s$%s", - arg_info->pass_by_reference ? "&" : "", + ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", ((zend_internal_arg_info*)arg_info)->name); } } else { name = zend_strpprintf(0, "%s$param%d", - arg_info->pass_by_reference ? "&" : "", + ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", i + 1); } ZVAL_NEW_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>")); @@ -583,9 +581,9 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{ } /* }}} */ -static HashTable *zend_closure_get_gc(zval *obj, zval **table, int *n) /* {{{ */ +static HashTable *zend_closure_get_gc(zend_object *obj, zval **table, int *n) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(obj); + zend_closure *closure = (zend_closure *)obj; *table = Z_TYPE(closure->this_ptr) != IS_NULL ? &closure->this_ptr : NULL; *n = Z_TYPE(closure->this_ptr) != IS_NULL ? 1 : 0; @@ -602,32 +600,12 @@ ZEND_COLD ZEND_METHOD(Closure, __construct) } /* }}} */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bindto, 0, 0, 1) - ZEND_ARG_INFO(0, newthis) - ZEND_ARG_INFO(0, newscope) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bind, 0, 0, 2) - ZEND_ARG_INFO(0, closure) - ZEND_ARG_INFO(0, newthis) - ZEND_ARG_INFO(0, newscope) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_call, 0, 0, 1) - ZEND_ARG_INFO(0, newthis) - ZEND_ARG_VARIADIC_INFO(0, parameters) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_fromcallable, 0, 0, 1) - ZEND_ARG_INFO(0, callable) -ZEND_END_ARG_INFO() - static const zend_function_entry closure_functions[] = { - ZEND_ME(Closure, __construct, NULL, ZEND_ACC_PRIVATE) - ZEND_ME(Closure, bind, arginfo_closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - ZEND_MALIAS(Closure, bindTo, bind, arginfo_closure_bindto, ZEND_ACC_PUBLIC) - ZEND_ME(Closure, call, arginfo_closure_call, ZEND_ACC_PUBLIC) - ZEND_ME(Closure, fromCallable, arginfo_closure_fromcallable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(Closure, __construct, arginfo_class_Closure___construct, ZEND_ACC_PRIVATE) + ZEND_ME(Closure, bind, arginfo_class_Closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_MALIAS(Closure, bindTo, bind, arginfo_class_Closure_bindTo, ZEND_ACC_PUBLIC) + ZEND_ME(Closure, call, arginfo_class_Closure_call, ZEND_ACC_PUBLIC) + ZEND_ME(Closure, fromCallable, arginfo_class_Closure_fromCallable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END }; @@ -651,7 +629,7 @@ void zend_register_closure_ce(void) /* {{{ */ closure_handlers.get_property_ptr_ptr = zend_closure_get_property_ptr_ptr; closure_handlers.has_property = zend_closure_has_property; closure_handlers.unset_property = zend_closure_unset_property; - closure_handlers.compare_objects = zend_closure_compare_objects; + closure_handlers.compare = zend_closure_compare; closure_handlers.clone_obj = zend_closure_clone; closure_handlers.get_debug_info = zend_closure_get_debug_info; closure_handlers.get_closure = zend_closure_get_closure; diff --git a/Zend/zend_closures.stub.php b/Zend/zend_closures.stub.php new file mode 100644 index 0000000000..ad15daa526 --- /dev/null +++ b/Zend/zend_closures.stub.php @@ -0,0 +1,20 @@ +<?php + +Class Closure +{ + private function __construct() {} + + /** @return ?Closure */ + static function bind(Closure $closure, ?object $newthis, $newscope = UNKNOWN) {} + + /** @return ?Closure */ + function bindTo(?object $newthis, $newscope = UNKNOWN) {} + + function call(object $newthis, ...$parameters) {} + + /** + * @param callable $callable Not a proper type annotation due to bug #78770 + * @return Closure + */ + function fromCallable($callable) {} +} diff --git a/Zend/zend_closures_arginfo.h b/Zend/zend_closures_arginfo.h new file mode 100644 index 0000000000..91d019dc94 --- /dev/null +++ b/Zend/zend_closures_arginfo.h @@ -0,0 +1,24 @@ +/* This is a generated file, edit the .stub.php file instead. */ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure___construct, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_bind, 0, 0, 2) + ZEND_ARG_OBJ_INFO(0, closure, Closure, 0) + ZEND_ARG_TYPE_INFO(0, newthis, IS_OBJECT, 1) + ZEND_ARG_INFO(0, newscope) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_bindTo, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, newthis, IS_OBJECT, 1) + ZEND_ARG_INFO(0, newscope) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_call, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, newthis, IS_OBJECT, 0) + ZEND_ARG_VARIADIC_INFO(0, parameters) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_fromCallable, 0, 0, 1) + ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ea24457394..be218e9e69 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -60,6 +60,10 @@ typedef struct _zend_loop_var { } zend_loop_var; static inline uint32_t zend_alloc_cache_slots(unsigned count) { + if (count == 0) { + return (uint32_t) -1; + } + zend_op_array *op_array = CG(active_op_array); uint32_t ret = op_array->cache_size; op_array->cache_size += count * sizeof(void*); @@ -71,7 +75,7 @@ static inline uint32_t zend_alloc_cache_slot(void) { } ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type); -ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename); +ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, const char *filename); #ifndef ZTS ZEND_API zend_compiler_globals compiler_globals; @@ -123,6 +127,7 @@ static void zend_destroy_property_info_internal(zval *zv) /* {{{ */ zend_property_info *property_info = Z_PTR_P(zv); zend_string_release(property_info->name); + zend_type_release(property_info->type, /* persistent */ 1); free(property_info); } /* }}} */ @@ -206,6 +211,8 @@ typedef struct _builtin_type_info { } builtin_type_info; static const builtin_type_info builtin_types[] = { + {ZEND_STRL("null"), IS_NULL}, + {ZEND_STRL("false"), IS_FALSE}, {ZEND_STRL("int"), IS_LONG}, {ZEND_STRL("float"), IS_DOUBLE}, {ZEND_STRL("string"), IS_STRING}, @@ -216,6 +223,19 @@ static const builtin_type_info builtin_types[] = { {NULL, 0, IS_UNDEF} }; +typedef struct { + const char *name; + size_t name_len; + const char *correct_name; +} confusable_type_info; + +static const confusable_type_info confusable_types[] = { + {ZEND_STRL("boolean"), "bool"}, + {ZEND_STRL("integer"), "int"}, + {ZEND_STRL("double"), "float"}, + {ZEND_STRL("resource"), NULL}, + {NULL, 0, NULL}, +}; static zend_always_inline zend_uchar zend_lookup_builtin_type_by_name(const zend_string *name) /* {{{ */ { @@ -233,6 +253,43 @@ static zend_always_inline zend_uchar zend_lookup_builtin_type_by_name(const zend } /* }}} */ +static zend_always_inline zend_bool zend_is_confusable_type(const zend_string *name, const char **correct_name) /* {{{ */ +{ + const confusable_type_info *info = confusable_types; + + /* Intentionally using case-sensitive comparison here, because "integer" is likely intended + * as a scalar type, while "Integer" is likely a class type. */ + for (; info->name; ++info) { + if (ZSTR_LEN(name) == info->name_len + && memcmp(ZSTR_VAL(name), info->name, info->name_len) == 0 + ) { + *correct_name = info->correct_name; + return 1; + } + } + + return 0; +} +/* }}} */ + +static void *zend_hash_find_ptr_lc(HashTable *ht, const char *str, size_t len) { + void *result; + zend_string *lcname; + ALLOCA_FLAG(use_heap); + + ZSTR_ALLOCA_ALLOC(lcname, len, use_heap); + zend_str_tolower_copy(ZSTR_VAL(lcname), str, len); + result = zend_hash_find_ptr(ht, lcname); + ZSTR_ALLOCA_FREE(lcname, use_heap); + + return result; +} + +static zend_bool zend_is_not_imported(zend_string *name) { + /* Assuming "name" is unqualified here. */ + return !FC(imports) + || zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), ZSTR_LEN(name)) == NULL; +} void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */ { @@ -464,17 +521,6 @@ static int lookup_cv(zend_string *name) /* {{{ */{ } /* }}} */ -void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */ -{ - zval_ptr_dtor_nogc(CT_CONSTANT_EX(op_array, n)); - if (n + 1 == op_array->last_literal) { - op_array->last_literal--; - } else { - ZVAL_UNDEF(CT_CONSTANT_EX(op_array, n)); - } -} -/* }}} */ - static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */ { ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); @@ -594,10 +640,6 @@ static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) zend_str_tolower(ZSTR_VAL(tmp_name), ns_len); zend_add_literal_string(&tmp_name); - /* lowercased namespace name & lowercased constant name */ - tmp_name = zend_string_tolower(name); - zend_add_literal_string(&tmp_name); - if (!unqualified) { return ret; } @@ -609,11 +651,6 @@ static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) tmp_name = zend_string_init(after_ns, after_ns_len, 0); zend_add_literal_string(&tmp_name); - /* lowercased unqualified constant name */ - tmp_name = zend_string_alloc(after_ns_len, 0); - zend_str_tolower_copy(ZSTR_VAL(tmp_name), after_ns, after_ns_len); - zend_add_literal_string(&tmp_name); - return ret; } /* }}} */ @@ -686,8 +723,21 @@ void zend_do_free(znode *op1) /* {{{ */ } if (opline->result_type == IS_TMP_VAR && opline->result.var == op1->u.op.var) { - if (opline->opcode == ZEND_BOOL || opline->opcode == ZEND_BOOL_NOT) { - return; + switch (opline->opcode) { + case ZEND_BOOL: + case ZEND_BOOL_NOT: + /* boolean resuls don't have to be freed */ + return; + case ZEND_POST_INC_STATIC_PROP: + case ZEND_POST_DEC_STATIC_PROP: + case ZEND_POST_INC_OBJ: + case ZEND_POST_DEC_OBJ: + case ZEND_POST_INC: + case ZEND_POST_DEC: + /* convert $i++ to ++$i */ + opline->opcode -= 2; + opline->result_type = IS_UNUSED; + return; } } @@ -811,19 +861,6 @@ zend_string *zend_prefix_with_ns(zend_string *name) { } } -void *zend_hash_find_ptr_lc(HashTable *ht, const char *str, size_t len) { - void *result; - zend_string *lcname; - ALLOCA_FLAG(use_heap); - - ZSTR_ALLOCA_ALLOC(lcname, len, use_heap); - zend_str_tolower_copy(ZSTR_VAL(lcname), str, len); - result = zend_hash_find_ptr(ht, lcname); - ZSTR_ALLOCA_FREE(lcname, use_heap); - - return result; -} - zend_string *zend_resolve_non_class_name( zend_string *name, uint32_t type, zend_bool *is_fully_qualified, zend_bool case_sensitive, HashTable *current_import_sub @@ -995,10 +1032,9 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ if (op_array->refcount) { (*op_array->refcount)++; } - if (op_array->static_variables) { - if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(op_array->static_variables); - } + if (op_array->static_variables + && !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(op_array->static_variables); } if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) { @@ -1098,6 +1134,108 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */ } /* }}} */ +static zend_string *add_type_string(zend_string *type, zend_string *new_type) { + zend_string *result; + if (type == NULL) { + return zend_string_copy(new_type); + } + + // TODO: Switch to smart_str? + result = zend_string_alloc(ZSTR_LEN(type) + ZSTR_LEN(new_type) + 1, 0); + memcpy(ZSTR_VAL(result), ZSTR_VAL(type), ZSTR_LEN(type)); + ZSTR_VAL(result)[ZSTR_LEN(type)] = '|'; + memcpy(ZSTR_VAL(result) + ZSTR_LEN(type) + 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type)); + ZSTR_VAL(result)[ZSTR_LEN(type) + ZSTR_LEN(new_type) + 1] = '\0'; + zend_string_release(type); + return result; +} + +static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scope) { + if (scope) { + if (zend_string_equals_literal_ci(name, "self")) { + name = scope->name; + } else if (zend_string_equals_literal_ci(name, "parent") && scope->parent) { + name = scope->parent->name; + } + } + return name; +} + +zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) { + zend_string *str = NULL; + if (ZEND_TYPE_HAS_LIST(type)) { + void *elem; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), elem) { + if (ZEND_TYPE_LIST_IS_CE(elem)) { + str = add_type_string(str, ZEND_TYPE_LIST_GET_CE(elem)->name); + } else { + str = add_type_string(str, + resolve_class_name(ZEND_TYPE_LIST_GET_NAME(elem), scope)); + } + } ZEND_TYPE_LIST_FOREACH_END(); + } else if (ZEND_TYPE_HAS_NAME(type)) { + str = zend_string_copy(resolve_class_name(ZEND_TYPE_NAME(type), scope)); + } else if (ZEND_TYPE_HAS_CE(type)) { + str = zend_string_copy(ZEND_TYPE_CE(type)->name); + } + + uint32_t type_mask = ZEND_TYPE_FULL_MASK(type); + if (type_mask & MAY_BE_CALLABLE) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE)); + } + if (type_mask & MAY_BE_ITERABLE) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ITERABLE)); + } + if (type_mask & MAY_BE_OBJECT) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT)); + } + if (type_mask & MAY_BE_ARRAY) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ARRAY)); + } + if (type_mask & MAY_BE_STRING) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_STRING)); + } + if (type_mask & MAY_BE_LONG) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_INT)); + } + if (type_mask & MAY_BE_DOUBLE) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FLOAT)); + } + if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_BOOL)); + } else if (type_mask & MAY_BE_FALSE) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FALSE)); + } + if (type_mask & MAY_BE_VOID) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_VOID)); + } + + if (type_mask & MAY_BE_NULL) { + zend_bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL; + if (!is_union) { + zend_string *nullable_str = zend_string_alloc(ZSTR_LEN(str) + 1, 0); + ZSTR_VAL(nullable_str)[0] = '?'; + memcpy(ZSTR_VAL(nullable_str) + 1, ZSTR_VAL(str), ZSTR_LEN(str)); + ZSTR_VAL(nullable_str)[ZSTR_LEN(nullable_str)] = '\0'; + zend_string_release(str); + return nullable_str; + } + + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE)); + } + return str; +} + +zend_string *zend_type_to_string(zend_type type) { + return zend_type_to_string_resolved(type, NULL); +} + +static zend_bool is_generator_compatible_class_type(zend_string *name) { + return zend_string_equals_literal_ci(name, "Traversable") + || zend_string_equals_literal_ci(name, "Iterator") + || zend_string_equals_literal_ci(name, "Generator"); +} + static void zend_mark_function_as_generator() /* {{{ */ { if (!CG(active_op_array)->function_name) { @@ -1106,20 +1244,32 @@ static void zend_mark_function_as_generator() /* {{{ */ } if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - zend_arg_info return_info = CG(active_op_array)->arg_info[-1]; - - if (ZEND_TYPE_CODE(return_info.type) != IS_ITERABLE) { - const char *msg = "Generators may only declare a return type of Generator, Iterator, Traversable, or iterable, %s is not permitted"; - - if (!ZEND_TYPE_IS_CLASS(return_info.type)) { - zend_error_noreturn(E_COMPILE_ERROR, msg, zend_get_type_by_const(ZEND_TYPE_CODE(return_info.type))); + zend_type return_type = CG(active_op_array)->arg_info[-1].type; + zend_bool valid_type = 0; + if (ZEND_TYPE_HAS_CLASS(return_type)) { + if (ZEND_TYPE_HAS_LIST(return_type)) { + void *entry; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(return_type), entry) { + ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + if (is_generator_compatible_class_type(ZEND_TYPE_LIST_GET_NAME(entry))) { + valid_type = 1; + break; + } + } ZEND_TYPE_LIST_FOREACH_END(); + } else { + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(return_type)); + valid_type = is_generator_compatible_class_type(ZEND_TYPE_NAME(return_type)); } + } else { + valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_ITERABLE) != 0; + } - if (!zend_string_equals_literal_ci(ZEND_TYPE_NAME(return_info.type), "Traversable") - && !zend_string_equals_literal_ci(ZEND_TYPE_NAME(return_info.type), "Iterator") - && !zend_string_equals_literal_ci(ZEND_TYPE_NAME(return_info.type), "Generator")) { - zend_error_noreturn(E_COMPILE_ERROR, msg, ZSTR_VAL(ZEND_TYPE_NAME(return_info.type))); - } + if (!valid_type) { + zend_string *str = zend_type_to_string(return_type); + zend_error_noreturn(E_COMPILE_ERROR, + "Generators may only declare a return type containing " \ + "Generator, Iterator, Traversable, or iterable, %s is not permitted", + ZSTR_VAL(str)); } } @@ -1259,26 +1409,13 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char } /* }}} */ -static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */ -{ - zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len); - if (c && !(ZEND_CONSTANT_FLAGS(c) & CONST_CS) && (ZEND_CONSTANT_FLAGS(c) & CONST_CT_SUBST)) { - return c; - } - return NULL; -} -/* }}} */ - static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */ { - zend_constant *c; - - /* Substitute case-sensitive (or lowercase) constants */ - c = zend_hash_find_ptr(EG(zend_constants), name); + zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name); if (c && ( ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) - && (!(ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) || !(CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) + && !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) )) { ZVAL_COPY_OR_DUP(zv, &c->value); @@ -1289,19 +1426,19 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i /* Substitute true, false and null (including unqualified usage in namespaces) */ const char *lookup_name = ZSTR_VAL(name); size_t lookup_len = ZSTR_LEN(name); + zval *val; if (!is_fully_qualified) { zend_get_unqualified_name(name, &lookup_name, &lookup_len); } - c = zend_lookup_reserved_const(lookup_name, lookup_len); - if (c) { - ZVAL_COPY_OR_DUP(zv, &c->value); + if ((val = zend_get_special_const(lookup_name, lookup_len))) { + ZVAL_COPY_VALUE(zv, val); return 1; } - } - return 0; + return 0; + } } /* }}} */ @@ -1370,7 +1507,7 @@ static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */ fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); } else if (fetch_type == ZEND_FETCH_CLASS_PARENT && !ce->parent_name) { - zend_error(E_DEPRECATED, + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"parent\" when current class scope has no parent"); } } @@ -1932,7 +2069,7 @@ static inline uint32_t zend_emit_jump(uint32_t opnum_target) /* {{{ */ } /* }}} */ -ZEND_API int zend_is_smart_branch(zend_op *opline) /* {{{ */ +ZEND_API int zend_is_smart_branch(const zend_op *opline) /* {{{ */ { switch (opline->opcode) { case ZEND_IS_IDENTICAL: @@ -1964,12 +2101,18 @@ static inline uint32_t zend_emit_cond_jump(zend_uchar opcode, znode *cond, uint3 uint32_t opnum = get_next_op_number(); zend_op *opline; - if ((cond->op_type & (IS_CV|IS_CONST)) - && opnum > 0 - && zend_is_smart_branch(CG(active_op_array)->opcodes + opnum - 1)) { - /* emit extra NOP to avoid incorrect SMART_BRANCH in very rare cases */ - zend_emit_op(NULL, ZEND_NOP, NULL, NULL); - opnum = get_next_op_number(); + if (cond->op_type == IS_TMP_VAR && opnum > 0) { + opline = CG(active_op_array)->opcodes + opnum - 1; + if (opline->result_type == IS_TMP_VAR + && opline->result.var == cond->u.op.var + && zend_is_smart_branch(opline)) { + if (opcode == ZEND_JMPZ) { + opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPZ; + } else { + ZEND_ASSERT(opcode == ZEND_JMPNZ); + opline->result_type = IS_TMP_VAR | IS_SMART_BRANCH_JMPNZ; + } + } } opline = zend_emit_op(NULL, opcode, cond, NULL); opline->op2.opline_num = opnum_target; @@ -2086,14 +2229,25 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */ } /* }}} */ +static size_t zend_type_get_num_classes(zend_type type) { + if (!ZEND_TYPE_HAS_CLASS(type)) { + return 0; + } + if (ZEND_TYPE_HAS_LIST(type)) { + return ZEND_TYPE_LIST(type)->num_types; + } + return 1; +} + static void zend_emit_return_type_check( znode *expr, zend_arg_info *return_info, zend_bool implicit) /* {{{ */ { - if (ZEND_TYPE_IS_SET(return_info->type)) { + zend_type type = return_info->type; + if (ZEND_TYPE_IS_SET(type)) { zend_op *opline; /* `return ...;` is illegal in a void function (but `return;` isn't) */ - if (ZEND_TYPE_CODE(return_info->type) == IS_VOID) { + if (ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) { if (expr) { if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) { zend_error_noreturn(E_COMPILE_ERROR, @@ -2108,7 +2262,7 @@ static void zend_emit_return_type_check( } if (!expr && !implicit) { - if (ZEND_TYPE_ALLOW_NULL(return_info->type)) { + if (ZEND_TYPE_ALLOW_NULL(type)) { zend_error_noreturn(E_COMPILE_ERROR, "A function with return type must return a value " "(did you mean \"return null;\" instead of \"return;\"?)"); @@ -2119,12 +2273,7 @@ static void zend_emit_return_type_check( } if (expr && expr->op_type == IS_CONST) { - if ((ZEND_TYPE_CODE(return_info->type) == Z_TYPE(expr->u.constant)) - ||((ZEND_TYPE_CODE(return_info->type) == _IS_BOOL) - && (Z_TYPE(expr->u.constant) == IS_FALSE - || Z_TYPE(expr->u.constant) == IS_TRUE)) - || (ZEND_TYPE_ALLOW_NULL(return_info->type) - && Z_TYPE(expr->u.constant) == IS_NULL)) { + if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) { /* we don't need run-time check */ return; } @@ -2135,12 +2284,8 @@ static void zend_emit_return_type_check( opline->result_type = expr->op_type = IS_TMP_VAR; opline->result.var = expr->u.op.var = get_temporary_variable(); } - if (ZEND_TYPE_IS_CLASS(return_info->type)) { - opline->op2.num = CG(active_op_array)->cache_size; - CG(active_op_array)->cache_size += sizeof(void*); - } else { - opline->op2.num = -1; - } + + opline->op2.num = zend_alloc_cache_slots(zend_type_get_num_classes(return_info->type)); } } /* }}} */ @@ -2388,6 +2533,16 @@ static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */ } /* }}} */ +static zend_bool this_guaranteed_exists() /* {{{ */ +{ + zend_op_array *op_array = CG(active_op_array); + /* Instance methods always have a $this. + * This also includes closures that have a scope and use $this. */ + return op_array->scope != NULL + && (op_array->fn_flags & ZEND_ACC_STATIC) == 0; +} +/* }}} */ + static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */ { if (is_this_fetch(ast)) { @@ -2490,14 +2645,14 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t zend_op *opline; if (is_this_fetch(obj_ast)) { - obj_node.op_type = IS_UNUSED; + if (this_guaranteed_exists()) { + obj_node.op_type = IS_UNUSED; + } else { + zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL); + } CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS; } else { opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); - if (opline && type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) { - opline->extended_value |= ZEND_FETCH_OBJ_WRITE; - } - zend_separate_if_call_and_write(&obj_node, obj_ast, type); } zend_compile_expr(&prop_node, prop_ast); @@ -2994,26 +3149,26 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ } arg_count++; - if (zend_is_variable_or_call(arg)) { - if (zend_is_call(arg)) { - zend_compile_var(&arg_node, arg, BP_VAR_R, 0); - if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { - /* Function call was converted into builtin instruction */ - opcode = ZEND_SEND_VAL; - } else { - if (fbc) { - if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAR_NO_REF; - } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAL; - } else { - opcode = ZEND_SEND_VAR; - } + if (zend_is_call(arg)) { + zend_compile_var(&arg_node, arg, BP_VAR_R, 0); + if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { + /* Function call was converted into builtin instruction */ + opcode = ZEND_SEND_VAL; + } else { + if (fbc) { + if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAR_NO_REF; + } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAL; } else { - opcode = ZEND_SEND_VAR_NO_REF_EX; + opcode = ZEND_SEND_VAR; } + } else { + opcode = ZEND_SEND_VAR_NO_REF_EX; } - } else if (fbc) { + } + } else if (zend_is_variable(arg)) { + if (fbc) { if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) { zend_compile_var(&arg_node, arg, BP_VAR_W, 1); opcode = ZEND_SEND_REF; @@ -3092,7 +3247,7 @@ ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc) if (fbc) { if (fbc->type == ZEND_INTERNAL_FUNCTION && !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) { if (init_op->opcode == ZEND_INIT_FCALL && !zend_execute_internal) { - if (!(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_RETURN_REFERENCE))) { + if (!(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED))) { return ZEND_DO_ICALL; } else { return ZEND_DO_FCALL_BY_NAME; @@ -3211,9 +3366,7 @@ int zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */ { znode arg_node; - if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) - || args->children != 1 - ) { + if (args->children != 1) { return FAILURE; } @@ -3249,6 +3402,21 @@ int zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t typ } /* }}} */ +static int zend_compile_func_is_scalar(znode *result, zend_ast_list *args) /* {{{ */ +{ + znode arg_node; + zend_op *opline; + + if (args->children != 1) { + return FAILURE; + } + + zend_compile_expr(&arg_node, args->child[0]); + opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL); + opline->extended_value = (1 << IS_FALSE | 1 << IS_TRUE | 1 << IS_DOUBLE | 1 << IS_LONG | 1 << IS_STRING); + return SUCCESS; +} + int zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */ { znode arg_node; @@ -3259,8 +3427,12 @@ int zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* } zend_compile_expr(&arg_node, args->child[0]); - opline = zend_emit_op_tmp(result, ZEND_CAST, &arg_node, NULL); - opline->extended_value = type; + if (type == _IS_BOOL) { + opline = zend_emit_op_tmp(result, ZEND_BOOL, &arg_node, NULL); + } else { + opline = zend_emit_op_tmp(result, ZEND_CAST, &arg_node, NULL); + opline->extended_value = type; + } return SUCCESS; } /* }}} */ @@ -3293,13 +3465,6 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */ LITERAL_STR(opline->op1, name); opline->extended_value = zend_alloc_cache_slot(); - /* Lowercase constant name in a separate literal */ - { - zval c; - zend_string *lcname = zend_string_tolower(name); - ZVAL_NEW_STR(&c, lcname); - zend_add_literal(&c); - } return SUCCESS; } /* }}} */ @@ -3770,6 +3935,8 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l return zend_compile_func_typecheck(result, args, IS_OBJECT); } else if (zend_string_equals_literal(lcname, "is_resource")) { return zend_compile_func_typecheck(result, args, IS_RESOURCE); + } else if (zend_string_equals_literal(lcname, "is_scalar")) { + return zend_compile_func_is_scalar(result, args); } else if (zend_string_equals_literal(lcname, "boolval")) { return zend_compile_func_cast(result, args, _IS_BOOL); } else if (zend_string_equals_literal(lcname, "intval")) { @@ -3897,7 +4064,11 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{ zend_function *fbc = NULL; if (is_this_fetch(obj_ast)) { - obj_node.op_type = IS_UNUSED; + if (this_guaranteed_exists()) { + obj_node.op_type = IS_UNUSED; + } else { + zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL); + } CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS; } else { zend_compile_expr(&obj_node, obj_ast); @@ -3942,6 +4113,24 @@ static zend_bool zend_is_constructor(zend_string *name) /* {{{ */ } /* }}} */ +static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */ +{ + zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname); + if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) { + return fbc; + } + + if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE) + && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED) + && (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) + && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) { + return fbc; + } + + return NULL; +} +/* }}} */ + void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *class_ast = ast->child[0]; @@ -4000,18 +4189,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{ } if (ce) { zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1); - fbc = zend_hash_find_ptr(&ce->function_table, lcname); - if (fbc && !(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { - if (ce != CG(active_class_entry) - && ((fbc->common.fn_flags & ZEND_ACC_PRIVATE) - || !(fbc->common.scope->ce_flags & ZEND_ACC_LINKED) - || (CG(active_class_entry) - && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) - || !zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry)))) { - /* incompatibe function */ - fbc = NULL; - } - } + fbc = zend_get_compatible_func_or_null(ce, lcname); } } @@ -5265,11 +5443,11 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */ n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM); i = 0; while (i < n) { - ZEND_SET_ARG_FLAG(func, i + 1, func->common.arg_info[i].pass_by_reference); + ZEND_SET_ARG_FLAG(func, i + 1, ZEND_ARG_SEND_MODE(&func->common.arg_info[i])); i++; } - if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && func->common.arg_info[i].pass_by_reference)) { - uint32_t pass_by_reference = func->common.arg_info[i].pass_by_reference; + if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && ZEND_ARG_SEND_MODE(&func->common.arg_info[i]))) { + uint32_t pass_by_reference = ZEND_ARG_SEND_MODE(&func->common.arg_info[i]); while (i < MAX_ARG_FLAG_NUM) { ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference); i++; @@ -5279,16 +5457,11 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */ } /* }}} */ -static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null) /* {{{ */ +static zend_type zend_compile_single_typename(zend_ast *ast) { - zend_bool allow_null = force_allow_null; - if (ast->attr & ZEND_TYPE_NULLABLE) { - allow_null = 1; - ast->attr &= ~ZEND_TYPE_NULLABLE; - } - + ZEND_ASSERT(!(ast->attr & ZEND_TYPE_NULLABLE)); if (ast->kind == ZEND_AST_TYPE) { - return ZEND_TYPE_ENCODE(ast->attr, allow_null); + return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, 0, 0); } else { zend_string *class_name = zend_ast_get_str(ast); zend_uchar type = zend_lookup_builtin_type_by_name(class_name); @@ -5299,8 +5472,10 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null "Type declaration '%s' must be unqualified", ZSTR_VAL(zend_string_tolower(class_name))); } - return ZEND_TYPE_ENCODE(type, allow_null); + return (zend_type) ZEND_TYPE_INIT_CODE(type, 0, 0); } else { + const char *correct_name; + zend_string *orig_name = zend_ast_get_str(ast); uint32_t fetch_type = zend_get_class_fetch_type_ast(ast); if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { class_name = zend_resolve_class_name_ast(ast); @@ -5310,12 +5485,181 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null zend_string_addref(class_name); } - return ZEND_TYPE_ENCODE_CLASS(class_name, allow_null); + if (ast->attr == ZEND_NAME_NOT_FQ + && zend_is_confusable_type(orig_name, &correct_name) + && zend_is_not_imported(orig_name)) { + const char *extra = + FC(current_namespace) ? " or import the class with \"use\"" : ""; + if (correct_name) { + zend_error(E_COMPILE_WARNING, + "\"%s\" will be interpreted as a class name. Did you mean \"%s\"? " + "Write \"\\%s\"%s to suppress this warning", + ZSTR_VAL(orig_name), correct_name, ZSTR_VAL(class_name), extra); + } else { + zend_error(E_COMPILE_WARNING, + "\"%s\" is not a supported builtin type " + "and will be interpreted as a class name. " + "Write \"\\%s\"%s to suppress this warning", + ZSTR_VAL(orig_name), ZSTR_VAL(class_name), extra); + } + } + + return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, 0, 0); + } + } +} + +static zend_bool zend_type_contains_traversable(zend_type type) { + if (ZEND_TYPE_HAS_LIST(type)) { + void *entry; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { + ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + if (zend_string_equals_literal_ci(ZEND_TYPE_LIST_GET_NAME(entry), "Traversable")) { + return 1; + } + } ZEND_TYPE_LIST_FOREACH_END(); + } else if (ZEND_TYPE_HAS_NAME(type)) { + return zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "Traversable"); + } + return 0; +} + +// TODO: Ideally we'd canonicalize "iterable" into "array|Traversable" and essentially +// treat it as a built-in type alias. +static zend_type zend_compile_typename( + zend_ast *ast, zend_bool force_allow_null, zend_bool use_arena) /* {{{ */ +{ + zend_bool allow_null = force_allow_null; + zend_type type = ZEND_TYPE_INIT_NONE(0); + if (ast->attr & ZEND_TYPE_NULLABLE) { + allow_null = 1; + ast->attr &= ~ZEND_TYPE_NULLABLE; + } + + if (ast->kind == ZEND_AST_TYPE_UNION) { + zend_ast_list *list = zend_ast_get_list(ast); + for (uint32_t i = 0; i < list->children; i++) { + zend_ast *type_ast = list->child[i]; + zend_type single_type = zend_compile_single_typename(type_ast); + uint32_t type_mask_overlap = + ZEND_TYPE_PURE_MASK(type) & ZEND_TYPE_PURE_MASK(single_type); + if (type_mask_overlap) { + zend_type overlap_type = ZEND_TYPE_INIT_MASK(type_mask_overlap); + zend_string *overlap_type_str = zend_type_to_string(overlap_type); + zend_error_noreturn(E_COMPILE_ERROR, + "Duplicate type %s is redundant", ZSTR_VAL(overlap_type_str)); + } + ZEND_TYPE_FULL_MASK(type) |= ZEND_TYPE_PURE_MASK(single_type); + + if (ZEND_TYPE_HAS_CLASS(single_type)) { + if (!ZEND_TYPE_HAS_CLASS(type)) { + /* The first class type can be stored directly as the type ptr payload. */ + ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type)); + ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT; + } else { + zend_type_list *list; + if (ZEND_TYPE_HAS_LIST(type)) { + /* Add name to existing name list. */ + zend_type_list *old_list = ZEND_TYPE_LIST(type); + if (use_arena) { + // TODO: Add a zend_arena_realloc API? + list = zend_arena_alloc( + &CG(arena), ZEND_TYPE_LIST_SIZE(old_list->num_types + 1)); + memcpy(list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types)); + } else { + list = erealloc(old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types + 1)); + } + list->types[list->num_types++] = ZEND_TYPE_NAME(single_type); + } else { + /* Switch from single name to name list. */ + size_t size = ZEND_TYPE_LIST_SIZE(2); + list = use_arena ? zend_arena_alloc(&CG(arena), size) : emalloc(size); + list->num_types = 2; + list->types[0] = ZEND_TYPE_NAME(type); + list->types[1] = ZEND_TYPE_NAME(single_type); + } + ZEND_TYPE_SET_LIST(type, list); + if (use_arena) { + ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT; + } + + /* Check for trivially redundant class types */ + for (size_t i = 0; i < list->num_types - 1; i++) { + if (zend_string_equals_ci( + ZEND_TYPE_LIST_GET_NAME(list->types[i]), + ZEND_TYPE_NAME(single_type))) { + zend_string *single_type_str = zend_type_to_string(single_type); + zend_error_noreturn(E_COMPILE_ERROR, + "Duplicate type %s is redundant", ZSTR_VAL(single_type_str)); + } + } + } + } + } + } else { + type = zend_compile_single_typename(ast); + } + + if (allow_null) { + ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL; + } + + uint32_t type_mask = ZEND_TYPE_PURE_MASK(type); + if ((type_mask & (MAY_BE_ARRAY|MAY_BE_ITERABLE)) == (MAY_BE_ARRAY|MAY_BE_ITERABLE)) { + zend_string *type_str = zend_type_to_string(type); + zend_error_noreturn(E_COMPILE_ERROR, + "Type %s contains both iterable and array, which is redundant", ZSTR_VAL(type_str)); + } + + if ((type_mask & MAY_BE_ITERABLE) && zend_type_contains_traversable(type)) { + zend_string *type_str = zend_type_to_string(type); + zend_error_noreturn(E_COMPILE_ERROR, + "Type %s contains both iterable and Traversable, which is redundant", + ZSTR_VAL(type_str)); + } + + if ((type_mask & MAY_BE_OBJECT) && ZEND_TYPE_HAS_CLASS(type)) { + zend_string *type_str = zend_type_to_string(type); + zend_error_noreturn(E_COMPILE_ERROR, + "Type %s contains both object and a class type, which is redundant", + ZSTR_VAL(type_str)); + } + + if ((type_mask & MAY_BE_VOID) && (ZEND_TYPE_HAS_CLASS(type) || type_mask != MAY_BE_VOID)) { + zend_error_noreturn(E_COMPILE_ERROR, "Void can only be used as a standalone type"); + } + + if ((type_mask & (MAY_BE_NULL|MAY_BE_FALSE)) + && !ZEND_TYPE_HAS_CLASS(type) && !(type_mask & ~(MAY_BE_NULL|MAY_BE_FALSE))) { + if (type_mask == MAY_BE_NULL) { + zend_error_noreturn(E_COMPILE_ERROR, "Null can not be used as a standalone type"); + } else { + zend_error_noreturn(E_COMPILE_ERROR, "False can not be used as a standalone type"); } } + + return type; } /* }}} */ +/* May convert value from int to float. */ +static zend_bool zend_is_valid_default_value(zend_type type, zval *value) +{ + ZEND_ASSERT(ZEND_TYPE_IS_SET(type)); + if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) { + return 1; + } + if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) { + /* Integers are allowed as initializers for floating-point values. */ + convert_to_double(value); + return 1; + } + if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) { + return 1; + } + return 0; +} + void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -5327,14 +5671,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ /* Use op_array->arg_info[-1] for return type */ arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0); arg_infos->name = NULL; - arg_infos->pass_by_reference = (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; - arg_infos->is_variadic = 0; - arg_infos->type = zend_compile_typename(return_type_ast, 0); - - if (ZEND_TYPE_CODE(arg_infos->type) == IS_VOID && ZEND_TYPE_ALLOW_NULL(arg_infos->type)) { - zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable"); - } - + arg_infos->type = zend_compile_typename( + return_type_ast, /* force_allow_null */ 0, /* use_arena */ 0); + ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS( + (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0); arg_infos++; op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE; } else { @@ -5402,75 +5742,26 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info = &arg_infos[i]; arg_info->name = zend_string_copy(name); - arg_info->pass_by_reference = is_ref; - arg_info->is_variadic = is_variadic; - /* TODO: Keep compatibility, but may be better reset "allow_null" ??? */ - arg_info->type = ZEND_TYPE_ENCODE(0, 1); + arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0); if (type_ast) { - zend_bool has_null_default = default_ast - && (Z_TYPE(default_node.u.constant) == IS_NULL - || (Z_TYPE(default_node.u.constant) == IS_CONSTANT_AST - && Z_ASTVAL(default_node.u.constant)->kind == ZEND_AST_CONSTANT - && strcasecmp(ZSTR_VAL(zend_ast_get_constant_name(Z_ASTVAL(default_node.u.constant))), "NULL") == 0)); + uint32_t default_type = default_ast ? Z_TYPE(default_node.u.constant) : IS_UNDEF; op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; - arg_info->type = zend_compile_typename(type_ast, has_null_default); + arg_info->type = zend_compile_typename( + type_ast, default_type == IS_NULL, /* use_arena */ 0); - if (ZEND_TYPE_CODE(arg_info->type) == IS_VOID) { + if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } - if (type_ast->kind == ZEND_AST_TYPE) { - if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY) { - if (default_ast && !has_null_default - && Z_TYPE(default_node.u.constant) != IS_ARRAY - && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST - ) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with array type can only be an array or NULL"); - } - } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE && default_ast) { - if (!has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with callable type can only be NULL"); - } - } - } else { - if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a class type can only be NULL"); - } else switch (ZEND_TYPE_CODE(arg_info->type)) { - case IS_DOUBLE: - if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a float type can only be float, integer, or NULL"); - } - convert_to_double(&default_node.u.constant); - break; - - case IS_ITERABLE: - if (Z_TYPE(default_node.u.constant) != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with iterable type can only be an array or NULL"); - } - break; - - case IS_OBJECT: - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with an object type can only be NULL"); - break; - - default: - if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a %s type can only be %s or NULL", - zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)), zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type))); - } - break; - } - } + if (default_type > IS_NULL && default_type != IS_CONSTANT_AST + && !zend_is_valid_default_value(arg_info->type, &default_node.u.constant)) { + zend_string *type_str = zend_type_to_string(arg_info->type); + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use %s as default value for parameter $%s of type %s", + zend_get_type_by_const(default_type), + ZSTR_VAL(name), ZSTR_VAL(type_str)); } } @@ -5480,23 +5771,11 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ if (type_ast) { /* Allocate cache slot to speed-up run-time class resolution */ - if (opline->opcode == ZEND_RECV_INIT) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->extended_value = zend_alloc_cache_slot(); - } - } else { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->op2.num = op_array->cache_size; - op_array->cache_size += sizeof(void*); - } else { - opline->op2.num = -1; - } - } - } else { - if (opline->opcode != ZEND_RECV_INIT) { - opline->op2.num = -1; - } + opline->extended_value = + zend_alloc_cache_slots(zend_type_get_num_classes(arg_info->type)); } + + ZEND_TYPE_FULL_MASK(arg_info->type) |= _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic); } /* These are assigned at the end to avoid uninitialized memory in case of an error */ @@ -5696,18 +5975,30 @@ static void zend_compile_implicit_closure_uses(closure_info *info) ZEND_HASH_FOREACH_END(); } +static void zend_check_magic_method_attr(uint32_t attr, const char* method, zend_bool is_static) /* {{{ */ +{ + if (is_static) { + if (!(attr & ZEND_ACC_PUBLIC) || !(attr & ZEND_ACC_STATIC)) { + zend_error(E_WARNING, "The magic method %s() must have public visibility and be static", method); + } + } else if (!(attr & ZEND_ACC_PUBLIC) || (attr & ZEND_ACC_STATIC)) { + zend_error(E_WARNING, + "The magic method %s() must have public visibility and cannot be static", + method); + } +} +/* }}} */ + void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */ { zend_class_entry *ce = CG(active_class_entry); zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0; - zend_bool in_trait = (ce->ce_flags & ZEND_ACC_TRAIT) != 0; - zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0; - zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0; + uint32_t fn_flags = op_array->fn_flags; zend_string *lcname; if (in_interface) { - if (!is_public || (op_array->fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { + if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method " "%s::%s() must be omitted", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } @@ -5742,134 +6033,48 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo ZSTR_VAL(ce->name), ZSTR_VAL(name)); } - if (in_interface) { - if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - /* pass */ - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - } - } else { - if (!in_trait && zend_string_equals_ci(lcname, ce->name)) { - if (!ce->constructor) { - ce->constructor = (zend_function *) op_array; - } - } else if (zend_string_equals_literal(lcname, "serialize")) { - ce->serialize_func = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, "unserialize")) { - ce->unserialize_func = (zend_function *) op_array; - } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - if (!is_static) { - op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; - } - } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { - ce->constructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { - ce->destructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { - ce->clone = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - ce->__call = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - ce->__callstatic = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - ce->__get = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - ce->__set = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - ce->__unset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - ce->__isset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - ce->__tostring = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - ce->__debugInfo = (zend_function *) op_array; - } else if (!is_static) { - op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; - } + if (zend_string_equals_literal(lcname, "serialize")) { + ce->serialize_func = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, "unserialize")) { + ce->unserialize_func = (zend_function *) op_array; + } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { + /* pass */ + } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { + ce->constructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { + ce->destructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { + ce->clone = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__call", 0); + ce->__call = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__callStatic", 1); + ce->__callstatic = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__get", 0); + ce->__get = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__set", 0); + ce->__set = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__unset", 0); + ce->__unset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__isset", 0); + ce->__isset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__toString", 0); + ce->__tostring = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__invoke", 0); + } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__debugInfo", 0); + ce->__debugInfo = (zend_function *) op_array; } zend_string_release_ex(lcname, 0); @@ -5878,7 +6083,6 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, zend_bool toplevel) /* {{{ */ { - zend_ast *params_ast = decl->child[0]; zend_string *unqualified_name, *name, *lcname, *key; zend_op *opline; @@ -5895,18 +6099,14 @@ static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_as } } - if (zend_string_equals_literal(lcname, ZEND_AUTOLOAD_FUNC_NAME)) { - if (zend_ast_get_list(params_ast)->children != 1) { - zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", - ZEND_AUTOLOAD_FUNC_NAME); - } - - zend_error(E_DEPRECATED, "__autoload() is deprecated, use spl_autoload_register() instead"); + if (zend_string_equals_literal(lcname, "__autoload")) { + zend_error_noreturn(E_COMPILE_ERROR, + "__autoload() is no longer supported, use spl_autoload_register() instead"); } if (zend_string_equals_literal_ci(unqualified_name, "assert")) { - zend_error(E_DEPRECATED, - "Defining a custom assert() function is deprecated, " + zend_error(E_COMPILE_ERROR, + "Defining a custom assert() function is not allowed, " "as the function has special semantics"); } @@ -6078,17 +6278,16 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) / zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast)); zend_string *doc_comment = NULL; zval value_zv; - zend_type type = 0; + zend_type type = ZEND_TYPE_INIT_NONE(0); if (type_ast) { - type = zend_compile_typename(type_ast, 0); + type = zend_compile_typename(type_ast, /* force_allow_null */ 0, /* use_arena */ 1); - if (ZEND_TYPE_CODE(type) == IS_VOID || ZEND_TYPE_CODE(type) == IS_CALLABLE) { + if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) { + zend_string *str = zend_type_to_string(type); zend_error_noreturn(E_COMPILE_ERROR, "Property %s::$%s cannot have type %s", - ZSTR_VAL(ce->name), - ZSTR_VAL(name), - zend_get_type_by_const(ZEND_TYPE_CODE(type))); + ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str)); } } @@ -6111,36 +6310,19 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) / if (value_ast) { zend_const_expr_to_zval(&value_zv, value_ast); - if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)) { + if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv) + && !zend_is_valid_default_value(type, &value_zv)) { + zend_string *str = zend_type_to_string(type); if (Z_TYPE(value_zv) == IS_NULL) { - if (!ZEND_TYPE_ALLOW_NULL(type)) { - const char *name = ZEND_TYPE_IS_CLASS(type) - ? ZSTR_VAL(ZEND_TYPE_NAME(type)) : zend_get_type_by_const(ZEND_TYPE_CODE(type)); - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s may not be null. " - "Use the nullable type ?%s to allow null default value", - name, name); - } - } else if (ZEND_TYPE_IS_CLASS(type)) { zend_error_noreturn(E_COMPILE_ERROR, - "Property of type %s may not have default value", ZSTR_VAL(ZEND_TYPE_NAME(type))); - } else if (ZEND_TYPE_CODE(type) == IS_ARRAY || ZEND_TYPE_CODE(type) == IS_ITERABLE) { - if (Z_TYPE(value_zv) != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s can only be an array", - zend_get_type_by_const(ZEND_TYPE_CODE(type))); - } - } else if (ZEND_TYPE_CODE(type) == IS_DOUBLE) { - if (Z_TYPE(value_zv) != IS_DOUBLE && Z_TYPE(value_zv) != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type float can only be float or int"); - } - convert_to_double(&value_zv); - } else if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(type), Z_TYPE(value_zv))) { + "Default value for property of type %s may not be null. " + "Use the nullable type ?%s to allow null default value", + ZSTR_VAL(str), ZSTR_VAL(str)); + } else { zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s can only be %s", - zend_get_type_by_const(ZEND_TYPE_CODE(type)), - zend_get_type_by_const(ZEND_TYPE_CODE(type))); + "Cannot use %s as default value for property %s::$%s of type %s", + zend_get_type_by_const(Z_TYPE(value_zv)), + ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str)); } } } else if (!ZEND_TYPE_IS_SET(type)) { @@ -6163,6 +6345,18 @@ void zend_compile_prop_group(zend_ast *list) /* {{{ */ } /* }}} */ +static void zend_check_const_and_trait_alias_attr(uint32_t attr, const char* entity) /* {{{ */ +{ + if (attr & ZEND_ACC_STATIC) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); + } else if (attr & ZEND_ACC_ABSTRACT) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity); + } else if (attr & ZEND_ACC_FINAL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity); + } +} +/* }}} */ + void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -6184,13 +6378,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zval value_zv; if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - if (ast->attr & ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier"); - } else if (ast->attr & ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier"); - } else if (ast->attr & ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier"); - } + zend_check_const_and_trait_alias_attr(ast->attr, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); @@ -6242,13 +6430,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ zend_trait_alias *alias; - if (modifiers == ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier"); - } else if (modifiers == ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier"); - } else if (modifiers == ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier"); - } + zend_check_const_and_trait_alias_attr(modifiers, "method"); alias = emalloc(sizeof(zend_trait_alias)); zend_compile_method_ref(method_ref_ast, &alias->trait_method); @@ -6446,11 +6628,6 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ /* Reset lineno for final opcodes and errors */ CG(zend_lineno) = ast->lineno; - if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) { - /* For traits this check is delayed until after trait binding */ - zend_check_deprecated_constructor(ce); - } - if (ce->constructor) { ce->constructor->common.fn_flags |= ZEND_ACC_CTOR; if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) { @@ -6519,13 +6696,11 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } CG(zend_lineno) = ast->lineno; } - } else { - if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { - zend_string_release(lcname); - zend_build_properties_info_table(ce); - ce->ce_flags |= ZEND_ACC_LINKED; - return NULL; - } + } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { + zend_string_release(lcname); + zend_build_properties_info_table(ce); + ce->ce_flags |= ZEND_ACC_LINKED; + return NULL; } } @@ -6660,11 +6835,6 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ new_name = zend_string_copy(old_name); if (!current_ns) { - if (type == T_CLASS && zend_string_equals_literal(new_name, "strict")) { - zend_error_noreturn(E_COMPILE_ERROR, - "You seem to be trying to use a different language..."); - } - zend_error(E_WARNING, "The use statement with non-compound name '%s' " "has no effect", ZSTR_VAL(new_name)); } @@ -6693,10 +6863,8 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ } zend_string_efree(ns_name); - } else { - if (zend_have_seen_symbol(lookup_name, type)) { - zend_check_already_in_use(type, old_name, new_name, lookup_name); - } + } else if (zend_have_seen_symbol(lookup_name, type)) { + zend_check_already_in_use(type, old_name, new_name, lookup_name); } zend_string_addref(old_name); @@ -6749,7 +6917,7 @@ void zend_compile_const_decl(zend_ast *ast) /* {{{ */ value_node.op_type = IS_CONST; zend_const_expr_to_zval(value_zv, value_ast); - if (zend_lookup_reserved_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) { + if (zend_get_special_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", ZSTR_VAL(unqualified_name)); } @@ -7162,12 +7330,10 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type"); break; } - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { - zval_ptr_dtor_nogc(value); - zval_ptr_dtor(result); - return 0; - } + } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { + zval_ptr_dtor_nogc(value); + zval_ptr_dtor(result); + return 0; } } @@ -7181,16 +7347,6 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */ zend_ast *right_ast = ast->child[1]; uint32_t opcode = ast->attr; - if ((opcode == ZEND_ADD || opcode == ZEND_SUB) && left_ast->kind == ZEND_AST_BINARY_OP && left_ast->attr == ZEND_CONCAT) { - zend_error(E_DEPRECATED, "The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence"); - } - if ((opcode == ZEND_SL || opcode == ZEND_SR) && ((left_ast->kind == ZEND_AST_BINARY_OP && left_ast->attr == ZEND_CONCAT) || (right_ast->kind == ZEND_AST_BINARY_OP && right_ast->attr == ZEND_CONCAT))) { - zend_error(E_DEPRECATED, "The behavior of unparenthesized expressions containing both '.' and '>>'/'<<' will change in PHP 8: '<<'/'>>' will take a higher precedence"); - } - if (opcode == ZEND_PARENTHESIZED_CONCAT) { - opcode = ZEND_CONCAT; - } - znode left_node, right_node; zend_compile_expr(&left_node, left_ast); zend_compile_expr(&right_node, right_ast); @@ -7229,8 +7385,28 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */ break; } } - } - if (opcode == ZEND_CONCAT) { + } else if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) { + /* convert $x === null to is_null($x) (i.e. ZEND_TYPE_CHECK opcode). Do the same thing for false/true. (covers IS_NULL, IS_FALSE, and IS_TRUE) */ + if (left_node.op_type == IS_CONST) { + if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) { + zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &right_node, NULL); + opline->extended_value = + (opcode == ZEND_IS_IDENTICAL) ? + (1 << Z_TYPE(left_node.u.constant)) : + (MAY_BE_ANY - (1 << Z_TYPE(left_node.u.constant))); + return; + } + } else if (right_node.op_type == IS_CONST) { + if (Z_TYPE(right_node.u.constant) <= IS_TRUE && Z_TYPE(right_node.u.constant) >= IS_NULL) { + zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &left_node, NULL); + opline->extended_value = + (opcode == ZEND_IS_IDENTICAL) ? + (1 << Z_TYPE(right_node.u.constant)) : + (MAY_BE_ANY - (1 << Z_TYPE(right_node.u.constant))); + return; + } + } + } else if (opcode == ZEND_CONCAT) { /* convert constant operands to strings at compile-time */ if (left_node.op_type == IS_CONST) { if (Z_TYPE(left_node.u.constant) == IS_ARRAY) { @@ -7313,12 +7489,11 @@ void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); - if (expr_node.op_type == IS_CONST) { - if (zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { - result->op_type = IS_CONST; - zval_ptr_dtor(&expr_node.u.constant); - return; - } + if (expr_node.op_type == IS_CONST + && zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { + result->op_type = IS_CONST; + zval_ptr_dtor(&expr_node.u.constant); + return; } lefthand_node.op_type = IS_CONST; @@ -7437,11 +7612,13 @@ void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); - opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL); - opline->extended_value = ast->attr; - - if (ast->attr == IS_NULL) { - zend_error(E_DEPRECATED, "The (unset) cast is deprecated"); + if (ast->attr == _IS_BOOL) { + opline = zend_emit_op_tmp(result, ZEND_BOOL, &expr_node, NULL); + } else if (ast->attr == IS_NULL) { + zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported"); + } else { + opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL); + opline->extended_value = ast->attr; } } /* }}} */ @@ -7994,19 +8171,13 @@ void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */ opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL); opline->op2_type = IS_CONST; - if (is_fully_qualified) { + if (is_fully_qualified || !FC(current_namespace)) { opline->op2.constant = zend_add_const_name_literal( resolved_name, 0); } else { - opline->op1.num = IS_CONSTANT_UNQUALIFIED; - if (FC(current_namespace)) { - opline->op1.num |= IS_CONSTANT_IN_NAMESPACE; - opline->op2.constant = zend_add_const_name_literal( - resolved_name, 1); - } else { - opline->op2.constant = zend_add_const_name_literal( - resolved_name, 0); - } + opline->op1.num = IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE; + opline->op2.constant = zend_add_const_name_literal( + resolved_name, 1); } opline->extended_value = zend_alloc_cache_slot(); } @@ -8337,7 +8508,8 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */ } zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_constant(resolved_name, !is_fully_qualified ? IS_CONSTANT_UNQUALIFIED : 0); + *ast_ptr = zend_ast_create_constant(resolved_name, + !is_fully_qualified && FC(current_namespace) ? IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE : 0); } /* }}} */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index c21554e464..a87204d267 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -51,7 +51,7 @@ typedef struct _zend_op zend_op; /* On 64-bit systems less optimal, but more compact VM code leads to better * performance. So on 32-bit systems we use absolute addresses for jump - * targets and constants, but on 64-bit systems realtive 32-bit offsets */ + * targets and constants, but on 64-bit systems relative 32-bit offsets */ #if SIZEOF_SIZE_T == 4 # define ZEND_USE_ABS_JMP_ADDR 1 # define ZEND_USE_ABS_CONST_ADDR 1 @@ -206,7 +206,7 @@ typedef struct _zend_oparray_context { /* Property or method overrides private one | | | */ #define ZEND_ACC_CHANGED (1 << 3) /* | X | X | */ /* | | | */ -/* Staic method or property | | | */ +/* Static method or property | | | */ #define ZEND_ACC_STATIC (1 << 4) /* | X | X | */ /* | | | */ /* Final class or method | | | */ @@ -237,10 +237,10 @@ typedef struct _zend_oparray_context { #define ZEND_ACC_TRAIT (1 << 1) /* X | | | */ #define ZEND_ACC_ANON_CLASS (1 << 2) /* X | | | */ /* | | | */ -/* Class linked with parent, interfacs and traits | | | */ +/* Class linked with parent, interfaces and traits | | | */ #define ZEND_ACC_LINKED (1 << 3) /* X | | | */ /* | | | */ -/* class is abstarct, since it is set by any | | | */ +/* Class is abstract, since it is set by any | | | */ /* abstract method | | | */ #define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS (1 << 4) /* X | | | */ /* | | | */ @@ -284,7 +284,7 @@ typedef struct _zend_oparray_context { /* Whether this class was used in its unlinked state. | | | */ #define ZEND_ACC_HAS_UNLINKED_USES (1 << 23) /* X | | | */ /* | | | */ -/* Function Flags (unused: 23, 26) | | | */ +/* Function Flags (unused: 17, 23, 26) | | | */ /* ============== | | | */ /* | | | */ /* deprecation flag | | | */ @@ -306,10 +306,6 @@ typedef struct _zend_oparray_context { /* ZEND_DECLARE_CLASS_DELAYED opcodes | | | */ #define ZEND_ACC_EARLY_BINDING (1 << 16) /* | X | | */ /* | | | */ -/* method flag (bc only), any method that has this | | | */ -/* flag can be used statically and non statically. | | | */ -#define ZEND_ACC_ALLOW_STATIC (1 << 17) /* | X | | */ -/* | | | */ /* call through user function trampoline. e.g. | | | */ /* __call, __callstatic | | | */ #define ZEND_ACC_CALL_VIA_TRAMPOLINE (1 << 18) /* | X | | */ @@ -387,16 +383,12 @@ typedef struct _zend_class_constant { typedef struct _zend_internal_arg_info { const char *name; zend_type type; - zend_uchar pass_by_reference; - zend_bool is_variadic; } zend_internal_arg_info; /* arg_info for user functions */ typedef struct _zend_arg_info { zend_string *name; zend_type type; - zend_uchar pass_by_reference; - zend_bool is_variadic; } zend_arg_info; /* the following structure repeats the layout of zend_internal_arg_info, @@ -407,8 +399,6 @@ typedef struct _zend_arg_info { typedef struct _zend_internal_function_info { zend_uintptr_t required_num_args; zend_type type; - zend_bool return_reference; - zend_bool _is_variadic; } zend_internal_function_info; struct _zend_op_array { @@ -493,7 +483,7 @@ union _zend_function { zend_function *prototype; uint32_t num_args; uint32_t required_num_args; - zend_arg_info *arg_info; + zend_arg_info *arg_info; /* index -1 represents the return value info, if any */ } common; zend_op_array op_array; @@ -706,6 +696,10 @@ struct _zend_execute_data { #define IS_VAR (1<<2) #define IS_CV (1<<3) /* Compiled variable */ +/* Used for result.type of smart branch instructions */ +#define IS_SMART_BRANCH_JMPZ (1<<4) +#define IS_SMART_BRANCH_JMPNZ (1<<5) + #define ZEND_EXTRA_VALUE 1 #include "zend_globals.h" @@ -722,7 +716,7 @@ void zend_file_context_begin(zend_file_context *prev_context); void zend_file_context_end(zend_file_context *prev_context); extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type); -extern ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename); +extern ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, const char *filename); ZEND_API int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem); void startup_scanner(void); @@ -780,7 +774,7 @@ ZEND_API void function_add_ref(zend_function *function); /* helper functions in zend_language_scanner.l */ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type); -ZEND_API zend_op_array *compile_string(zval *source_string, char *filename); +ZEND_API zend_op_array *compile_string(zval *source_string, const char *filename); ZEND_API zend_op_array *compile_filename(int type, zval *filename); ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...); ZEND_API int open_file_for_scanning(zend_file_handle *file_handle); @@ -789,6 +783,8 @@ ZEND_API void destroy_op_array(zend_op_array *op_array); ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle); ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce); ZEND_API void zend_cleanup_internal_classes(void); +ZEND_API void zend_type_release(zend_type type, zend_bool persistent); + ZEND_API ZEND_COLD void zend_user_exception_handler(void); @@ -830,7 +826,7 @@ ZEND_API char *zend_make_compiled_string_description(const char *name); ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers); uint32_t zend_get_class_fetch_type(zend_string *name); ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc); -ZEND_API int zend_is_smart_branch(zend_op *opline); +ZEND_API int zend_is_smart_branch(const zend_op *opline); typedef zend_bool (*zend_auto_global_callback)(zend_string *name); typedef struct _zend_auto_global { @@ -851,6 +847,9 @@ int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem); void zend_assert_valid_class_name(const zend_string *const_name); +zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope); +zend_string *zend_type_to_string(zend_type type); + /* BEGIN: OPCODES */ #include "zend_vm_opcodes.h" @@ -893,14 +892,11 @@ void zend_assert_valid_class_name(const zend_string *const_name); #define BP_VAR_FUNC_ARG 4 #define BP_VAR_UNSET 5 -#define ZEND_INTERNAL_FUNCTION 1 -#define ZEND_USER_FUNCTION 2 -#define ZEND_OVERLOADED_FUNCTION 3 -#define ZEND_EVAL_CODE 4 -#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5 +#define ZEND_INTERNAL_FUNCTION 1 +#define ZEND_USER_FUNCTION 2 +#define ZEND_EVAL_CODE 4 -/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */ -#define ZEND_USER_CODE(type) ((type & 1) == 0) +#define ZEND_USER_CODE(type) ((type) != ZEND_INTERNAL_FUNCTION) #define ZEND_INTERNAL_CLASS 1 #define ZEND_USER_CLASS 2 @@ -921,7 +917,6 @@ void zend_assert_valid_class_name(const zend_string *const_name); /* Only one of these can ever be in use */ #define ZEND_FETCH_REF 1 #define ZEND_FETCH_DIM_WRITE 2 -#define ZEND_FETCH_OBJ_WRITE 3 #define ZEND_FETCH_OBJ_FLAGS 3 #define ZEND_ISEMPTY (1<<0) @@ -935,12 +930,20 @@ void zend_assert_valid_class_name(const zend_string *const_name); #define ZEND_SEND_BY_REF 1u #define ZEND_SEND_PREFER_REF 2u +/* The send mode and is_variadic flag are stored as part of zend_type */ +#define _ZEND_SEND_MODE_SHIFT _ZEND_TYPE_EXTRA_FLAGS_SHIFT +#define _ZEND_IS_VARIADIC_BIT (1 << (_ZEND_TYPE_EXTRA_FLAGS_SHIFT + 2)) +#define ZEND_ARG_SEND_MODE(arg_info) \ + ((ZEND_TYPE_FULL_MASK((arg_info)->type) >> _ZEND_SEND_MODE_SHIFT) & 3) +#define ZEND_ARG_IS_VARIADIC(arg_info) \ + ((ZEND_TYPE_FULL_MASK((arg_info)->type) & _ZEND_IS_VARIADIC_BIT) != 0) + #define ZEND_DIM_IS (1 << 0) /* isset fetch needed for null coalesce */ #define ZEND_DIM_ALTERNATIVE_SYNTAX (1 << 1) /* deprecated curly brace usage */ -#define IS_CONSTANT_UNQUALIFIED 0x010 -#define IS_CONSTANT_CLASS 0x080 /* __CLASS__ in trait */ -#define IS_CONSTANT_IN_NAMESPACE 0x100 +/* Make sure these don't clash with ZEND_FETCH_CLASS_* flags. */ +#define IS_CONSTANT_CLASS 0x400 /* __CLASS__ in trait */ +#define IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE 0x800 static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, uint32_t arg_num, uint32_t mask) { @@ -951,7 +954,7 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, } arg_num = zf->common.num_args; } - return UNEXPECTED((zf->common.arg_info[arg_num].pass_by_reference & mask) != 0); + return UNEXPECTED((ZEND_ARG_SEND_MODE(&zf->common.arg_info[arg_num]) & mask) != 0); } #define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \ @@ -1018,11 +1021,11 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, (((opcode) >= ZEND_ADD) && ((opcode) <= ZEND_POW)) /* Pseudo-opcodes that are used only temporarily during compilation */ -#define ZEND_PARENTHESIZED_CONCAT 252 /* removed with PHP 8 */ #define ZEND_GOTO 253 #define ZEND_BRK 254 #define ZEND_CONT 255 + END_EXTERN_C() #define ZEND_CLONE_FUNC_NAME "__clone" @@ -1035,7 +1038,6 @@ END_EXTERN_C() #define ZEND_CALL_FUNC_NAME "__call" #define ZEND_CALLSTATIC_FUNC_NAME "__callstatic" #define ZEND_TOSTRING_FUNC_NAME "__tostring" -#define ZEND_AUTOLOAD_FUNC_NAME "__autoload" #define ZEND_INVOKE_FUNC_NAME "__invoke" #define ZEND_DEBUGINFO_FUNC_NAME "__debuginfo" @@ -1064,9 +1066,6 @@ END_EXTERN_C() /* disable constant substitution at compile-time */ #define ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION (1<<6) -/* disable usage of builtin instruction for strlen() */ -#define ZEND_COMPILE_NO_BUILTIN_STRLEN (1<<7) - /* disable substitution of persistent constants at compile-time */ #define ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION (1<<8) diff --git a/Zend/zend_config.w32.h b/Zend/zend_config.w32.h index 19a5165e4b..47387895e5 100644 --- a/Zend/zend_config.w32.h +++ b/Zend/zend_config.w32.h @@ -47,18 +47,6 @@ #endif #define strcasecmp(s1, s2) _stricmp(s1, s2) #define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) -#if defined(__cplusplus) && __cplusplus >= 201103L -extern "C++" { -#include <cmath> -#define zend_isnan std::isnan -#define zend_isinf std::isinf -#define zend_finite std::isfinite -} -#else -#define zend_isinf(a) ((_fpclass(a) == _FPCLASS_PINF) || (_fpclass(a) == _FPCLASS_NINF)) -#define zend_finite(x) _finite(x) -#define zend_isnan(x) _isnan(x) -#endif #ifndef __cplusplus /* This will cause the compilation process to be MUCH longer, but will generate diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 49ee762c60..3148180a9a 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -33,6 +33,9 @@ #define MARK_CONSTANT_VISITED(zv) Z_ACCESS_FLAGS_P(zv) |= IS_CONSTANT_VISITED_MARK #define RESET_CONSTANT_VISITED(zv) Z_ACCESS_FLAGS_P(zv) &= ~IS_CONSTANT_VISITED_MARK +/* Use for special null/true/false constants. */ +static zval null_value, true_value, false_value; + void free_zend_constant(zval *zv) { zend_constant *c = Z_PTR_P(zv); @@ -99,7 +102,6 @@ void clean_module_constants(int module_number) int zend_startup_constants(void) { EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init(EG(zend_constants), 128, NULL, ZEND_CONSTANT_DTOR, 1); return SUCCESS; } @@ -128,14 +130,17 @@ void zend_register_standard_constants(void) REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS); - /* true/false constants */ - { - REGISTER_MAIN_BOOL_CONSTANT("TRUE", 1, CONST_PERSISTENT | CONST_CT_SUBST); - REGISTER_MAIN_BOOL_CONSTANT("FALSE", 0, CONST_PERSISTENT | CONST_CT_SUBST); - REGISTER_MAIN_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT | CONST_CS); - } - REGISTER_MAIN_NULL_CONSTANT("NULL", CONST_PERSISTENT | CONST_CT_SUBST); + REGISTER_MAIN_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT | CONST_CS); + + /* Special constants true/false/null. */ + REGISTER_MAIN_BOOL_CONSTANT("TRUE", 1, CONST_PERSISTENT); + REGISTER_MAIN_BOOL_CONSTANT("FALSE", 0, CONST_PERSISTENT); + REGISTER_MAIN_NULL_CONSTANT("NULL", CONST_PERSISTENT); + + ZVAL_NULL(&null_value); + ZVAL_TRUE(&true_value); + ZVAL_FALSE(&false_value); } @@ -188,7 +193,7 @@ ZEND_API void zend_register_double_constant(const char *name, size_t name_len, d } -ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number) +ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number) { zend_constant c; @@ -199,12 +204,12 @@ ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, } -ZEND_API void zend_register_string_constant(const char *name, size_t name_len, char *strval, int flags, int module_number) +ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number) { zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number); } -static zend_constant *zend_get_special_constant(const char *name, size_t name_len) +static zend_constant *zend_get_halt_offset_constant(const char *name, size_t name_len) { zend_constant *c; static const char haltoff[] = "__COMPILER_HALT_OFFSET__"; @@ -230,6 +235,37 @@ static zend_constant *zend_get_special_constant(const char *name, size_t name_le } } +ZEND_API zval *_zend_get_special_const(const char *name, size_t len) /* {{{ */ +{ + if (len == 4) { + if ((name[0] == 'n' || name[0] == 'N') && + (name[1] == 'u' || name[1] == 'U') && + (name[2] == 'l' || name[2] == 'L') && + (name[3] == 'l' || name[3] == 'L') + ) { + return &null_value; + } + if ((name[0] == 't' || name[0] == 'T') && + (name[1] == 'r' || name[1] == 'R') && + (name[2] == 'u' || name[2] == 'U') && + (name[3] == 'e' || name[3] == 'E') + ) { + return &true_value; + } + } else { + if ((name[0] == 'f' || name[0] == 'F') && + (name[1] == 'a' || name[1] == 'A') && + (name[2] == 'l' || name[2] == 'L') && + (name[3] == 's' || name[3] == 'S') && + (name[4] == 'e' || name[4] == 'E') + ) { + return &false_value; + } + } + return 0; +} +/* }}} */ + ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry *scope) /* {{{ */ { if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) { @@ -243,80 +279,34 @@ ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry * } /* }}} */ -static inline zend_constant *zend_get_constant_str_impl(const char *name, size_t name_len) -{ - zend_constant *c; - ALLOCA_FLAG(use_heap) - - if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) { - char *lcname = do_alloca(name_len + 1, use_heap); - zend_str_tolower_copy(lcname, name, name_len); - if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) { - if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) { - c = NULL; - } - } else { - c = zend_get_special_constant(name, name_len); - } - free_alloca(lcname, use_heap); - } - - return c; -} - ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len) { - zend_constant *c = zend_get_constant_str_impl(name, name_len); - return c ? &c->value : NULL; -} + zend_constant *c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len); + if (c) { + return &c->value; + } -static inline zend_constant *zend_get_constant_impl(zend_string *name) -{ - zval *zv; - zend_constant *c; - ALLOCA_FLAG(use_heap) - - zv = zend_hash_find(EG(zend_constants), name); - if (zv == NULL) { - char *lcname = do_alloca(ZSTR_LEN(name) + 1, use_heap); - zend_str_tolower_copy(lcname, ZSTR_VAL(name), ZSTR_LEN(name)); - zv = zend_hash_str_find(EG(zend_constants), lcname, ZSTR_LEN(name)); - if (zv != NULL) { - c = Z_PTR_P(zv); - if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) { - c = NULL; - } - } else { - c = zend_get_special_constant(ZSTR_VAL(name), ZSTR_LEN(name)); - } - free_alloca(lcname, use_heap); - return c; - } else { - return (zend_constant *) Z_PTR_P(zv); + c = zend_get_halt_offset_constant(name, name_len); + if (c) { + return &c->value; } + + return zend_get_special_const(name, name_len); } ZEND_API zval *zend_get_constant(zend_string *name) { - zend_constant *c = zend_get_constant_impl(name); - return c ? &c->value : NULL; -} + zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name); + if (c) { + return &c->value; + } -static zend_bool is_access_deprecated(const zend_constant *c, const char *access_name) { - const char *ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name)); - if (ns_sep) { - /* Namespaces are always case-insensitive. Only compare shortname. */ - size_t shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1; - size_t shortname_len = ZSTR_LEN(c->name) - shortname_offset; - return memcmp( - access_name + shortname_offset, - ZSTR_VAL(c->name) + shortname_offset, - shortname_len - ) != 0; - } else { - /* No namespace, compare whole name */ - return memcmp(access_name, ZSTR_VAL(c->name), ZSTR_LEN(c->name)) != 0; + c = zend_get_halt_offset_constant(ZSTR_VAL(name), ZSTR_LEN(name)); + if (c) { + return &c->value; } + + return zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name)); } ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags) @@ -421,56 +411,34 @@ failure: size_t lcname_len; ALLOCA_FLAG(use_heap) + /* Lowercase the namespace portion */ lcname_len = prefix_len + 1 + const_name_len; lcname = do_alloca(lcname_len + 1, use_heap); zend_str_tolower_copy(lcname, name, prefix_len); - /* Check for namespace constant */ lcname[prefix_len] = '\\'; memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1); - if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) { - /* try lowercase */ - zend_str_tolower(lcname + prefix_len + 1, const_name_len); - if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) { - if ((ZEND_CONSTANT_FLAGS(c) & CONST_CS) != 0) { - c = NULL; - } - } - } + c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len); free_alloca(lcname, use_heap); - if (!c) { - if (!(flags & IS_CONSTANT_UNQUALIFIED)) { - return NULL; - } + if (c) { + return &c->value; + } - /* name requires runtime resolution, need to check non-namespaced name */ - c = zend_get_constant_str_impl(constant_name, const_name_len); - name = constant_name; + if (!(flags & IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE)) { + return NULL; } + + /* name requires runtime resolution, need to check non-namespaced name */ + return zend_get_constant_str(constant_name, const_name_len); } else { if (cname) { - c = zend_get_constant_impl(cname); + return zend_get_constant(cname); } else { - c = zend_get_constant_str_impl(name, name_len); - } - } - - if (!c) { - return NULL; - } - - if (!(flags & ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) { - if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST)) && is_access_deprecated(c, name)) { - zend_error(E_DEPRECATED, - "Case-insensitive constants are deprecated. " - "The correct casing for this constant is \"%s\"", - ZSTR_VAL(c->name)); + return zend_get_constant_str(name, name_len); } } - - return &c->value; } static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c) @@ -491,38 +459,30 @@ ZEND_API int zend_register_constant(zend_constant *c) zend_string *lowercase_name = NULL; zend_string *name; int ret = SUCCESS; + zend_bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0; #if 0 printf("Registering constant for module %d\n", c->module_number); #endif - if (!(ZEND_CONSTANT_FLAGS(c) & CONST_CS)) { - lowercase_name = zend_string_tolower_ex(c->name, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT); + char *slash = strrchr(ZSTR_VAL(c->name), '\\'); + if (slash) { + lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), persistent); + zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name)); lowercase_name = zend_new_interned_string(lowercase_name); name = lowercase_name; } else { - char *slash = strrchr(ZSTR_VAL(c->name), '\\'); - if (slash) { - lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT); - zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name)); - lowercase_name = zend_new_interned_string(lowercase_name); - name = lowercase_name; - } else { - name = c->name; - } + name = c->name; } - /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */ + /* Check if the user is trying to define any special constant */ if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__") - || zend_hash_add_constant(EG(zend_constants), name, c) == NULL) { - - /* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */ - if (ZSTR_VAL(c->name)[0] == '\0' && ZSTR_LEN(c->name) > sizeof("\0__COMPILER_HALT_OFFSET__")-1 - && memcmp(ZSTR_VAL(name), "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) { - } + || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name))) + || zend_hash_add_constant(EG(zend_constants), name, c) == NULL + ) { zend_error(E_NOTICE,"Constant %s already defined", ZSTR_VAL(name)); zend_string_release(c->name); - if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) { + if (!persistent) { zval_ptr_dtor_nogc(&c->value); } ret = FAILURE; diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index ba0c798dc6..75be4c32b2 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -22,16 +22,12 @@ #include "zend_globals.h" -#define CONST_CS (1<<0) /* Case Sensitive */ -#define CONST_PERSISTENT (1<<1) /* Persistent */ -#define CONST_CT_SUBST (1<<2) /* Allow compile-time substitution */ -#define CONST_NO_FILE_CACHE (1<<3) /* Can't be saved in file cache */ +#define CONST_CS 0 /* No longer used -- always case sensitive */ +#define CONST_PERSISTENT (1<<0) /* Persistent */ +#define CONST_NO_FILE_CACHE (1<<1) /* Can't be saved in file cache */ #define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */ -/* Flag for zend_get_constant_ex(). Must not class with ZEND_FETCH_CLASS_* flags. */ -#define ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK 0x1000 - typedef struct _zend_constant { zval value; zend_string *name; @@ -83,12 +79,22 @@ ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, zen ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number); ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number); ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number); -ZEND_API void zend_register_string_constant(const char *name, size_t name_len, char *strval, int flags, int module_number); -ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number); +ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number); +ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number); ZEND_API int zend_register_constant(zend_constant *c); #ifdef ZTS void zend_copy_constants(HashTable *target, HashTable *sourc); #endif + +ZEND_API zval *_zend_get_special_const(const char *name, size_t name_len); + +static zend_always_inline zval *zend_get_special_const(const char *name, size_t name_len) { + if (name_len == 4 || name_len == 5) { + return _zend_get_special_const(name, name_len); + } + return NULL; +} + END_EXTERN_C() #define ZEND_CONSTANT_DTOR free_zend_constant diff --git a/Zend/zend_cpuinfo.h b/Zend/zend_cpuinfo.h index c0949e3638..0b6b54e51a 100644 --- a/Zend/zend_cpuinfo.h +++ b/Zend/zend_cpuinfo.h @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@zend.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Xinchen Hui <xinchen.h@zend.com> | + | Authors: Xinchen Hui <laruence@php.net> | +----------------------------------------------------------------------+ */ diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h index 441458c033..dd7539523d 100644 --- a/Zend/zend_errors.h +++ b/Zend/zend_errors.h @@ -36,7 +36,15 @@ #define E_DEPRECATED (1<<13L) #define E_USER_DEPRECATED (1<<14L) +/* Indicates that this usually fatal error should not result in a bailout */ +#define E_DONT_BAIL (1<<15L) + #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT) #define E_CORE (E_CORE_ERROR | E_CORE_WARNING) +/* Fatal errors that are ignored by the silence operator */ +#define E_FATAL_ERRORS (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE) + +#define E_HAS_ONLY_FATAL_ERRORS(mask) !((mask) & ~E_FATAL_ERRORS) + #endif /* ZEND_ERRORS_H */ diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 8672ed8e00..19ec415c73 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -27,6 +27,7 @@ #include "zend_vm.h" #include "zend_dtrace.h" #include "zend_smart_str.h" +#include "zend_exceptions_arginfo.h" ZEND_API zend_class_entry *zend_ce_throwable; ZEND_API zend_class_entry *zend_ce_exception; @@ -36,6 +37,7 @@ ZEND_API zend_class_entry *zend_ce_compile_error; ZEND_API zend_class_entry *zend_ce_parse_error; ZEND_API zend_class_entry *zend_ce_type_error; ZEND_API zend_class_entry *zend_ce_argument_count_error; +ZEND_API zend_class_entry *zend_ce_value_error; ZEND_API zend_class_entry *zend_ce_arithmetic_error; ZEND_API zend_class_entry *zend_ce_division_by_zero_error; @@ -156,8 +158,9 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zval *exception) /* {{{ */ if (exception && (Z_OBJCE_P(exception) == zend_ce_parse_error || Z_OBJCE_P(exception) == zend_ce_compile_error)) { return; } - if(EG(exception)) { + if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR); + zend_bailout(); } zend_error_noreturn(E_CORE_ERROR, "Exception thrown without a stack frame"); } @@ -629,7 +632,8 @@ ZEND_METHOD(exception, getTraceAsString) trace = zend_read_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_TRACE), 1, &rv); if (Z_TYPE_P(trace) != IS_ARRAY) { - RETURN_FALSE; + zend_type_error("trace is not an array"); + return; } ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) { if (Z_TYPE_P(frame) != IS_ARRAY) { @@ -757,14 +761,14 @@ ZEND_METHOD(exception, __toString) /** {{{ Throwable method definition */ static const zend_function_entry zend_funcs_throwable[] = { - ZEND_ABSTRACT_ME(throwable, getMessage, NULL) - ZEND_ABSTRACT_ME(throwable, getCode, NULL) - ZEND_ABSTRACT_ME(throwable, getFile, NULL) - ZEND_ABSTRACT_ME(throwable, getLine, NULL) - ZEND_ABSTRACT_ME(throwable, getTrace, NULL) - ZEND_ABSTRACT_ME(throwable, getPrevious, NULL) - ZEND_ABSTRACT_ME(throwable, getTraceAsString, NULL) - ZEND_ABSTRACT_ME(throwable, __toString, NULL) + ZEND_ABSTRACT_ME(throwable, getMessage, arginfo_class_Throwable_getMessage) + ZEND_ABSTRACT_ME(throwable, getCode, arginfo_class_Throwable_getCode) + ZEND_ABSTRACT_ME(throwable, getFile, arginfo_class_Throwable_getFile) + ZEND_ABSTRACT_ME(throwable, getLine, arginfo_class_Throwable_getLine) + ZEND_ABSTRACT_ME(throwable, getTrace, arginfo_class_Throwable_getTrace) + ZEND_ABSTRACT_ME(throwable, getPrevious, arginfo_class_Throwable_getPrevious) + ZEND_ABSTRACT_ME(throwable, getTraceAsString, arginfo_class_Throwable_getTraceAsString) + ZEND_ABSTRACT_ME(throwable, __toString, arginfo_class_Throwable___toString) ZEND_FE_END }; /* }}} */ @@ -779,39 +783,24 @@ static const zend_function_entry zend_funcs_throwable[] = { * And never try to change the state of exceptions and never implement anything * that gives the user anything to accomplish this. */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_exception___construct, 0, 0, 0) - ZEND_ARG_INFO(0, message) - ZEND_ARG_INFO(0, code) - ZEND_ARG_INFO(0, previous) -ZEND_END_ARG_INFO() - static const zend_function_entry default_exception_functions[] = { - ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL) - ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC) - ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC) - ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - ZEND_ME(exception, getPrevious, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - ZEND_ME(exception, __toString, NULL, 0) + ZEND_ME(exception, __clone, arginfo_class_Exception___clone, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL) + ZEND_ME(exception, __construct, arginfo_class_Exception___construct, ZEND_ACC_PUBLIC) + ZEND_ME(exception, __wakeup, arginfo_class_Exception___wakeup, ZEND_ACC_PUBLIC) + ZEND_ME(exception, getMessage, arginfo_class_Exception_getMessage, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(exception, getCode, arginfo_class_Exception_getCode, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(exception, getFile, arginfo_class_Exception_getFile, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(exception, getLine, arginfo_class_Exception_getLine, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(exception, getTrace, arginfo_class_Exception_getTrace, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(exception, getPrevious, arginfo_class_Exception_getPrevious, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(exception, getTraceAsString, arginfo_class_Exception_getTraceAsString, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(exception, __toString, arginfo_class_Exception___toString, 0) ZEND_FE_END }; -ZEND_BEGIN_ARG_INFO_EX(arginfo_error_exception___construct, 0, 0, 0) - ZEND_ARG_INFO(0, message) - ZEND_ARG_INFO(0, code) - ZEND_ARG_INFO(0, severity) - ZEND_ARG_INFO(0, filename) - ZEND_ARG_INFO(0, lineno) - ZEND_ARG_INFO(0, previous) -ZEND_END_ARG_INFO() - static const zend_function_entry error_exception_functions[] = { - ZEND_ME(error_exception, __construct, arginfo_error_exception___construct, ZEND_ACC_PUBLIC) - ZEND_ME(error_exception, getSeverity, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) + ZEND_ME(error_exception, __construct, arginfo_class_ErrorException___construct, ZEND_ACC_PUBLIC) + ZEND_ME(error_exception, getSeverity, arginfo_class_ErrorException_getSeverity, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_FE_END }; /* }}} */ @@ -872,6 +861,10 @@ void zend_register_default_exception(void) /* {{{ */ zend_ce_argument_count_error = zend_register_internal_class_ex(&ce, zend_ce_type_error); zend_ce_argument_count_error->create_object = zend_default_exception_new; + INIT_CLASS_ENTRY(ce, "ValueError", NULL); + zend_ce_value_error = zend_register_internal_class_ex(&ce, zend_ce_error); + zend_ce_value_error->create_object = zend_default_exception_new; + INIT_CLASS_ENTRY(ce, "ArithmeticError", NULL); zend_ce_arithmetic_error = zend_register_internal_class_ex(&ce, zend_ce_error); zend_ce_arithmetic_error->create_object = zend_default_exception_new; @@ -986,7 +979,8 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* { zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE)); zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE)); - zend_error_helper(ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR, + zend_error_helper( + (ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR) | E_DONT_BAIL, ZSTR_VAL(file), line, "%s", ZSTR_VAL(message)); zend_string_release_ex(file, 0); @@ -996,7 +990,7 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* { zend_string *str, *file = NULL; zend_long line = 0; - zend_call_method_with_0_params(&exception, ce_exception, &ex->ce->__tostring, "__tostring", &tmp); + zend_call_method_with_0_params(Z_OBJ(exception), ce_exception, &ex->ce->__tostring, "__tostring", &tmp); if (!EG(exception)) { if (Z_TYPE(tmp) != IS_STRING) { zend_error(E_WARNING, "%s::__toString() must return a string", ZSTR_VAL(ce_exception->name)); @@ -1029,7 +1023,8 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* { file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE)); line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE)); - zend_error_va(severity, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line, + zend_error_va(severity | E_DONT_BAIL, + (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line, "Uncaught %s\n thrown", ZSTR_VAL(str)); zend_string_release_ex(str, 0); diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 5f31c4b25b..ec6f0a0201 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -32,6 +32,7 @@ extern ZEND_API zend_class_entry *zend_ce_compile_error; extern ZEND_API zend_class_entry *zend_ce_parse_error; extern ZEND_API zend_class_entry *zend_ce_type_error; extern ZEND_API zend_class_entry *zend_ce_argument_count_error; +extern ZEND_API zend_class_entry *zend_ce_value_error; extern ZEND_API zend_class_entry *zend_ce_arithmetic_error; extern ZEND_API zend_class_entry *zend_ce_division_by_zero_error; diff --git a/Zend/zend_exceptions.stub.php b/Zend/zend_exceptions.stub.php new file mode 100644 index 0000000000..96d581caf9 --- /dev/null +++ b/Zend/zend_exceptions.stub.php @@ -0,0 +1,68 @@ +<?php + +interface Throwable +{ + /** @return string */ + function getMessage(); + + /** @return int */ + function getCode(); + + /** @return string */ + function getFile(); + + /** @return int */ + function getLine(); + + /** @return array */ + function getTrace(); + + /** @return ?Throwable */ + function getPrevious(); + + /** @return string */ + function getTraceAsString(); + + /** @return string */ + function __toString(); +} + +class Exception implements Throwable +{ + final private function __clone() {} + + function __construct(string $message = UNKNOWN, int $code = 0, ?Throwable $previous = null) {} + + function __wakeup() {} + + /** @return string */ + final function getMessage() {} + + /** @return int */ + final function getCode() {} + + /** @return string */ + final function getFile() {} + + /** @return int */ + final function getLine() {} + + /** @return array */ + final function getTrace() {} + + /** @return ?Throwable */ + final function getPrevious() {} + + /** @return string */ + final function getTraceAsString() {} + + /** @return string */ + function __toString() {} +} + +class ErrorException extends Exception +{ + function __construct(string $message = UNKNOWN, int $code = 0, int $severity = E_ERROR, string $filename = UNKNOWN, int $lineno = 0, ?Throwable $previous = null) {} + + final function getSeverity() {} +} diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h new file mode 100644 index 0000000000..c2f83e47e5 --- /dev/null +++ b/Zend/zend_exceptions_arginfo.h @@ -0,0 +1,55 @@ +/* This is a generated file, edit the .stub.php file instead. */ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Throwable_getMessage, 0, 0, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Throwable_getCode arginfo_class_Throwable_getMessage + +#define arginfo_class_Throwable_getFile arginfo_class_Throwable_getMessage + +#define arginfo_class_Throwable_getLine arginfo_class_Throwable_getMessage + +#define arginfo_class_Throwable_getTrace arginfo_class_Throwable_getMessage + +#define arginfo_class_Throwable_getPrevious arginfo_class_Throwable_getMessage + +#define arginfo_class_Throwable_getTraceAsString arginfo_class_Throwable_getMessage + +#define arginfo_class_Throwable___toString arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception___clone arginfo_class_Throwable_getMessage + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Exception___construct, 0, 0, 0) + ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, code, IS_LONG, 0) + ZEND_ARG_OBJ_INFO(0, previous, Throwable, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_Exception___wakeup arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception_getMessage arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception_getCode arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception_getFile arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception_getLine arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception_getTrace arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception_getPrevious arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception_getTraceAsString arginfo_class_Throwable_getMessage + +#define arginfo_class_Exception___toString arginfo_class_Throwable_getMessage + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ErrorException___construct, 0, 0, 0) + ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, code, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, severity, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, lineno, IS_LONG, 0) + ZEND_ARG_OBJ_INFO(0, previous, Throwable, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_ErrorException_getSeverity arginfo_class_Throwable_getMessage diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c1ff85bff8..548438bb29 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -39,6 +39,7 @@ #include "zend_dtrace.h" #include "zend_inheritance.h" #include "zend_type_info.h" +#include "zend_smart_str.h" /* Virtual current working directory support */ #include "zend_virtual_cwd.h" @@ -109,16 +110,16 @@ typedef int (ZEND_FASTCALL *incdec_t)(zval *); -#define get_zval_ptr(op_type, node, should_free, type) _get_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC) -#define get_zval_ptr_deref(op_type, node, should_free, type) _get_zval_ptr_deref(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC) -#define get_zval_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC) -#define get_op_data_zval_ptr_r(op_type, node, should_free) _get_op_data_zval_ptr_r(op_type, node, should_free EXECUTE_DATA_CC OPLINE_CC) -#define get_op_data_zval_ptr_deref_r(op_type, node, should_free) _get_op_data_zval_ptr_deref_r(op_type, node, should_free EXECUTE_DATA_CC OPLINE_CC) -#define get_zval_ptr_ptr(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC) -#define get_zval_ptr_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC) -#define get_obj_zval_ptr(op_type, node, should_free, type) _get_obj_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC) -#define get_obj_zval_ptr_undef(op_type, node, should_free, type) _get_obj_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC) -#define get_obj_zval_ptr_ptr(op_type, node, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC) +#define get_zval_ptr(op_type, node, type) _get_zval_ptr(op_type, node, type EXECUTE_DATA_CC OPLINE_CC) +#define get_zval_ptr_deref(op_type, node, type) _get_zval_ptr_deref(op_type, node, type EXECUTE_DATA_CC OPLINE_CC) +#define get_zval_ptr_undef(op_type, node, type) _get_zval_ptr_undef(op_type, node, type EXECUTE_DATA_CC OPLINE_CC) +#define get_op_data_zval_ptr_r(op_type, node) _get_op_data_zval_ptr_r(op_type, node EXECUTE_DATA_CC OPLINE_CC) +#define get_op_data_zval_ptr_deref_r(op_type, node) _get_op_data_zval_ptr_deref_r(op_type, node EXECUTE_DATA_CC OPLINE_CC) +#define get_zval_ptr_ptr(op_type, node, type) _get_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC) +#define get_zval_ptr_ptr_undef(op_type, node, type) _get_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC) +#define get_obj_zval_ptr(op_type, node, type) _get_obj_zval_ptr(op_type, node, type EXECUTE_DATA_CC OPLINE_CC) +#define get_obj_zval_ptr_undef(op_type, node, type) _get_obj_zval_ptr_undef(op_type, node, type EXECUTE_DATA_CC OPLINE_CC) +#define get_obj_zval_ptr_ptr(op_type, node, type) _get_obj_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC) #define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED) @@ -141,13 +142,12 @@ ZEND_API const zend_internal_function zend_pass_function = { {NULL,NULL,NULL,NULL} /* reserved */ }; -#define FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op, result) do { \ - zval *__container_to_free = (free_op); \ - if (UNEXPECTED(__container_to_free) \ - && EXPECTED(Z_REFCOUNTED_P(__container_to_free))) { \ +#define FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_var) do { \ + zval *__container_to_free = EX_VAR(free_var); \ + if (UNEXPECTED(Z_REFCOUNTED_P(__container_to_free))) { \ zend_refcounted *__ref = Z_COUNTED_P(__container_to_free); \ if (UNEXPECTED(!GC_DELREF(__ref))) { \ - zval *__zv = (result); \ + zval *__zv = EX_VAR(opline->result.var); \ if (EXPECTED(Z_TYPE_P(__zv) == IS_INDIRECT)) { \ ZVAL_COPY(__zv, Z_INDIRECT_P(__zv)); \ } \ @@ -156,20 +156,16 @@ ZEND_API const zend_internal_function zend_pass_function = { } \ } while (0) -#define FREE_OP(should_free) \ - if (should_free) { \ - zval_ptr_dtor_nogc(should_free); \ - } - -#define FREE_UNFETCHED_OP(type, var) \ +#define FREE_OP(type, var) \ if ((type) & (IS_TMP_VAR|IS_VAR)) { \ zval_ptr_dtor_nogc(EX_VAR(var)); \ } -#define FREE_OP_VAR_PTR(should_free) \ - if (should_free) { \ - zval_ptr_dtor_nogc(should_free); \ - } +#define FREE_UNFETCHED_OP(type, var) \ + FREE_OP(type, var) + +#define FREE_OP_VAR_PTR(type, var) \ + FREE_OP(type, var) #define CV_DEF_OF(i) (EX(func)->op_array.vars[i]) @@ -241,29 +237,26 @@ ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute return EX_VAR(var); } -static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC) +static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var EXECUTE_DATA_DC) { zval *ret = EX_VAR(var); - *should_free = ret; ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE); return ret; } -static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC) +static zend_always_inline zval *_get_zval_ptr_var(uint32_t var EXECUTE_DATA_DC) { zval *ret = EX_VAR(var); - *should_free = ret; return ret; } -static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC) +static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var EXECUTE_DATA_DC) { zval *ret = EX_VAR(var); - *should_free = ret; ZVAL_DEREF(ret); return ret; } @@ -272,7 +265,7 @@ static zend_never_inline ZEND_COLD zval* zval_undefined_cv(uint32_t var EXECUTE_ { if (EXPECTED(EG(exception) == NULL)) { zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var)); - zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(cv)); } return &EG(uninitialized_zval); } @@ -390,17 +383,16 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_D return ret; } -static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC) +static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC) { if (op_type & (IS_TMP_VAR|IS_VAR)) { if (!ZEND_DEBUG || op_type == IS_VAR) { - return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_var(node.var EXECUTE_DATA_CC); } else { ZEND_ASSERT(op_type == IS_TMP_VAR); - return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC); } } else { - *should_free = NULL; if (op_type == IS_CONST) { return RT_CONSTANT(opline, node); } else if (op_type == IS_CV) { @@ -411,17 +403,16 @@ static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, zend_f } } -static zend_always_inline zval *_get_op_data_zval_ptr_r(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC OPLINE_DC) +static zend_always_inline zval *_get_op_data_zval_ptr_r(int op_type, znode_op node EXECUTE_DATA_DC OPLINE_DC) { if (op_type & (IS_TMP_VAR|IS_VAR)) { if (!ZEND_DEBUG || op_type == IS_VAR) { - return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_var(node.var EXECUTE_DATA_CC); } else { ZEND_ASSERT(op_type == IS_TMP_VAR); - return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC); } } else { - *should_free = NULL; if (op_type == IS_CONST) { return RT_CONSTANT(opline + 1, node); } else if (op_type == IS_CV) { @@ -432,17 +423,16 @@ static zend_always_inline zval *_get_op_data_zval_ptr_r(int op_type, znode_op no } } -static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_zval_ptr_deref(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC) +static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_zval_ptr_deref(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC) { if (op_type & (IS_TMP_VAR|IS_VAR)) { if (op_type == IS_TMP_VAR) { - return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC); } else { ZEND_ASSERT(op_type == IS_VAR); - return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC); } } else { - *should_free = NULL; if (op_type == IS_CONST) { return RT_CONSTANT(opline, node); } else if (op_type == IS_CV) { @@ -453,17 +443,16 @@ static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_zval_ptr_deref(int op } } -static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_op_data_zval_ptr_deref_r(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC OPLINE_DC) +static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_op_data_zval_ptr_deref_r(int op_type, znode_op node EXECUTE_DATA_DC OPLINE_DC) { if (op_type & (IS_TMP_VAR|IS_VAR)) { if (op_type == IS_TMP_VAR) { - return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC); } else { ZEND_ASSERT(op_type == IS_VAR); - return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC); } } else { - *should_free = NULL; if (op_type == IS_CONST) { return RT_CONSTANT(opline + 1, node); } else if (op_type == IS_CV) { @@ -474,17 +463,16 @@ static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_op_data_zval_ptr_dere } } -static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC) +static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC) { if (op_type & (IS_TMP_VAR|IS_VAR)) { if (!ZEND_DEBUG || op_type == IS_VAR) { - return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_var(node.var EXECUTE_DATA_CC); } else { ZEND_ASSERT(op_type == IS_TMP_VAR); - return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC); } } else { - *should_free = NULL; if (op_type == IS_CONST) { return RT_CONSTANT(opline, node); } else if (op_type == IS_CV) { @@ -495,55 +483,48 @@ static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, } } -static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC) +static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var EXECUTE_DATA_DC) { zval *ret = EX_VAR(var); if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - *should_free = NULL; ret = Z_INDIRECT_P(ret); - } else { - *should_free = ret; } return ret; } -static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC) +static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC) { if (op_type == IS_CV) { - *should_free = NULL; return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC); } else /* if (op_type == IS_VAR) */ { ZEND_ASSERT(op_type == IS_VAR); - return _get_zval_ptr_ptr_var(node.var, should_free EXECUTE_DATA_CC); + return _get_zval_ptr_ptr_var(node.var EXECUTE_DATA_CC); } } -static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC) +static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr(int op_type, znode_op op, int type EXECUTE_DATA_DC OPLINE_DC) { if (op_type == IS_UNUSED) { - *should_free = NULL; return &EX(This); } - return get_zval_ptr(op_type, op, should_free, type); + return get_zval_ptr(op_type, op, type); } -static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC) +static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, int type EXECUTE_DATA_DC OPLINE_DC) { if (op_type == IS_UNUSED) { - *should_free = NULL; return &EX(This); } - return get_zval_ptr_undef(op_type, op, should_free, type); + return get_zval_ptr_undef(op_type, op, type); } -static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC) +static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC) { if (op_type == IS_UNUSED) { - *should_free = NULL; return &EX(This); } - return get_zval_ptr_ptr(op_type, node, should_free, type); + return get_zval_ptr_ptr(op_type, node, type); } static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr) @@ -602,39 +583,26 @@ static zend_never_inline ZEND_COLD int zend_wrong_assign_to_variable_reference(z return 1; } -static void zend_format_type(zend_type type, const char **part1, const char **part2) { - *part1 = ZEND_TYPE_ALLOW_NULL(type) ? "?" : ""; - if (ZEND_TYPE_IS_CLASS(type)) { - if (ZEND_TYPE_IS_CE(type)) { - *part2 = ZSTR_VAL(ZEND_TYPE_CE(type)->name); - } else { - *part2 = ZSTR_VAL(ZEND_TYPE_NAME(type)); - } - } else { - *part2 = zend_get_type_by_const(ZEND_TYPE_CODE(type)); - } -} - static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_prop_error(zend_property_info *prop, const char *type) { - const char *prop_type1, *prop_type2; - zend_format_type(prop->type, &prop_type1, &prop_type2); + zend_string *type_str = zend_type_to_string(prop->type); zend_type_error( - "Cannot auto-initialize an %s inside property %s::$%s of type %s%s", + "Cannot auto-initialize an %s inside property %s::$%s of type %s", type, ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name), - prop_type1, prop_type2 + ZSTR_VAL(type_str) ); + zend_string_release(type_str); } static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_ref_error(zend_property_info *prop, const char *type) { - const char *prop_type1, *prop_type2; - zend_format_type(prop->type, &prop_type1, &prop_type2); + zend_string *type_str = zend_type_to_string(prop->type); zend_type_error( - "Cannot auto-initialize an %s inside a reference held by property %s::$%s of type %s%s", + "Cannot auto-initialize an %s inside a reference held by property %s::$%s of type %s", type, ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name), - prop_type1, prop_type2 + ZSTR_VAL(type_str) ); + zend_string_release(type_str); } static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_error( @@ -645,80 +613,60 @@ static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_err zend_get_unmangled_property_name(prop->name)); } -static zend_never_inline zend_bool zend_verify_ref_stdClass_assignable(zend_reference *ref); -static zend_never_inline zend_bool zend_verify_ref_array_assignable(zend_reference *ref); - /* this should modify object only if it's empty */ -static zend_never_inline ZEND_COLD zval* ZEND_FASTCALL make_real_object(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC) -{ - zend_object *obj; - zval *ref = NULL; - if (Z_ISREF_P(object)) { - ref = object; - object = Z_REFVAL_P(object); - } - - if (UNEXPECTED(Z_TYPE_P(object) > IS_FALSE && - (Z_TYPE_P(object) != IS_STRING || Z_STRLEN_P(object) != 0))) { - if (opline->op1_type != IS_VAR || EXPECTED(!Z_ISERROR_P(object))) { - zend_string *tmp_property_name; - zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name); - - if (opline->opcode == ZEND_PRE_INC_OBJ - || opline->opcode == ZEND_PRE_DEC_OBJ - || opline->opcode == ZEND_POST_INC_OBJ - || opline->opcode == ZEND_POST_DEC_OBJ) { - zend_error(E_WARNING, "Attempt to increment/decrement property '%s' of non-object", ZSTR_VAL(property_name)); - } else if (opline->opcode == ZEND_FETCH_OBJ_W - || opline->opcode == ZEND_FETCH_OBJ_RW - || opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG - || opline->opcode == ZEND_ASSIGN_OBJ_REF) { - zend_error(E_WARNING, "Attempt to modify property '%s' of non-object", ZSTR_VAL(property_name)); - } else { - zend_error(E_WARNING, "Attempt to assign property '%s' of non-object", ZSTR_VAL(property_name)); - } - zend_tmp_string_release(tmp_property_name); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - return NULL; +static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_throw_non_object_error(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC) +{ + zend_string *tmp_property_name; + zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name); + + if (opline->opcode == ZEND_PRE_INC_OBJ + || opline->opcode == ZEND_PRE_DEC_OBJ + || opline->opcode == ZEND_POST_INC_OBJ + || opline->opcode == ZEND_POST_DEC_OBJ) { + zend_throw_error(NULL, + "Attempt to increment/decrement property '%s' of non-object", + ZSTR_VAL(property_name)); + } else if (opline->opcode == ZEND_FETCH_OBJ_W + || opline->opcode == ZEND_FETCH_OBJ_RW + || opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG + || opline->opcode == ZEND_ASSIGN_OBJ_REF) { + zend_throw_error(NULL, + "Attempt to modify property '%s' of non-object", ZSTR_VAL(property_name)); + } else { + zend_throw_error(NULL, + "Attempt to assign property '%s' of non-object", ZSTR_VAL(property_name)); } + zend_tmp_string_release(tmp_property_name); - if (ref && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(ref))) { - if (UNEXPECTED(!zend_verify_ref_stdClass_assignable(Z_REF_P(ref)))) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - return NULL; - } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } +} - zval_ptr_dtor_nogc(object); - object_init(object); - Z_ADDREF_P(object); - obj = Z_OBJ_P(object); - zend_error(E_WARNING, "Creating default object from empty value"); - if (GC_REFCOUNT(obj) == 1) { - /* the enclosing container was deleted, obj is unreferenced */ - OBJ_RELEASE(obj); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - return NULL; +/* Test used to preserve old error messages for non-union types. + * We might want to canonicalize all type errors instead. */ +static zend_bool is_union_type(zend_type type) { + if (ZEND_TYPE_HAS_LIST(type)) { + return 1; + } + uint32_t type_mask_without_null = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type); + if (ZEND_TYPE_HAS_CLASS(type)) { + return type_mask_without_null != 0; } - Z_DELREF_P(object); - return object; + if (type_mask_without_null == MAY_BE_BOOL) { + return 0; + } + /* Check that only one bit is set. */ + return (type_mask_without_null & (type_mask_without_null - 1)) != 0; } static ZEND_COLD void zend_verify_type_error_common( const zend_function *zf, const zend_arg_info *arg_info, - const zend_class_entry *ce, zval *value, + void **cache_slot, zval *value, const char **fname, const char **fsep, const char **fclass, - const char **need_msg, const char **need_kind, const char **need_or_null, - const char **given_msg, const char **given_kind) + zend_string **need_msg, const char **given_msg, const char **given_kind) { - zend_bool is_interface = 0; + smart_str str = {0}; *fname = ZSTR_VAL(zf->common.function_name); if (zf->common.scope) { *fsep = "::"; @@ -728,50 +676,69 @@ static ZEND_COLD void zend_verify_type_error_common( *fclass = ""; } - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + if (is_union_type(arg_info->type)) { + zend_string *type_str = zend_type_to_string(arg_info->type); + smart_str_appends(&str, "be of type "); + smart_str_append(&str, type_str); + zend_string_release(type_str); + } else if (ZEND_TYPE_HAS_CLASS(arg_info->type)) { + zend_bool is_interface = 0; + zend_class_entry *ce = *cache_slot; + if (!ce) { + ce = zend_fetch_class(ZEND_TYPE_NAME(arg_info->type), + (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); + } if (ce) { if (ce->ce_flags & ZEND_ACC_INTERFACE) { - *need_msg = "implement interface "; + smart_str_appends(&str, "implement interface "); is_interface = 1; } else { - *need_msg = "be an instance of "; + smart_str_appends(&str, "be an instance of "); } - *need_kind = ZSTR_VAL(ce->name); + smart_str_append(&str, ce->name); } else { /* We don't know whether it's a class or interface, assume it's a class */ + smart_str_appends(&str, "be an instance of "); + smart_str_append(&str, ZEND_TYPE_NAME(arg_info->type)); + } - *need_msg = "be an instance of "; - *need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)); + if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) { + smart_str_appends(&str, is_interface ? " or be null" : " or null"); } } else { - switch (ZEND_TYPE_CODE(arg_info->type)) { - case IS_OBJECT: - *need_msg = "be an "; - *need_kind = "object"; + uint32_t type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(arg_info->type); + switch (type_mask) { + case MAY_BE_OBJECT: + smart_str_appends(&str, "be an object"); break; - case IS_CALLABLE: - *need_msg = "be callable"; - *need_kind = ""; + case MAY_BE_CALLABLE: + smart_str_appends(&str, "be callable"); break; - case IS_ITERABLE: - *need_msg = "be iterable"; - *need_kind = ""; + case MAY_BE_ITERABLE: + smart_str_appends(&str, "be iterable"); break; default: - *need_msg = "be of the type "; - *need_kind = zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)); + { + /* Hack to print the type without null */ + zend_type type = arg_info->type; + ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_NULL; + zend_string *type_str = zend_type_to_string(type); + smart_str_appends(&str, "be of the type "); + smart_str_append(&str, type_str); + zend_string_release(type_str); break; + } } - } - if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) { - *need_or_null = is_interface ? " or be null" : " or null"; - } else { - *need_or_null = ""; + if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) { + smart_str_appends(&str, " or null"); + } } + *need_msg = smart_str_extract(&str); + if (value) { - if (ZEND_TYPE_IS_CLASS(arg_info->type) && Z_TYPE_P(value) == IS_OBJECT) { + if (ZEND_TYPE_HAS_CLASS(arg_info->type) && Z_TYPE_P(value) == IS_OBJECT) { *given_msg = "instance of "; *given_kind = ZSTR_VAL(Z_OBJCE_P(value)->name); } else { @@ -784,13 +751,14 @@ static ZEND_COLD void zend_verify_type_error_common( } } -static ZEND_COLD void zend_verify_arg_error( +ZEND_API ZEND_COLD void zend_verify_arg_error( const zend_function *zf, const zend_arg_info *arg_info, - int arg_num, const zend_class_entry *ce, zval *value) + int arg_num, void **cache_slot, zval *value) { zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data; const char *fname, *fsep, *fclass; - const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind; + zend_string *need_msg; + const char *given_msg, *given_kind; if (EG(exception)) { /* The type verification itself might have already thrown an exception @@ -800,186 +768,234 @@ static ZEND_COLD void zend_verify_arg_error( if (value) { zend_verify_type_error_common( - zf, arg_info, ce, value, - &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind); + zf, arg_info, cache_slot, value, + &fname, &fsep, &fclass, &need_msg, &given_msg, &given_kind); if (zf->common.type == ZEND_USER_FUNCTION) { if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { - zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given, called in %s on line %d", - arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind, + zend_type_error("Argument %d passed to %s%s%s() must %s, %s%s given, called in %s on line %d", + arg_num, fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg, given_kind, ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno); } else { - zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind); + zend_type_error("Argument %d passed to %s%s%s() must %s, %s%s given", arg_num, fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg, given_kind); } } else { - zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind); + zend_type_error("Argument %d passed to %s%s%s() must %s, %s%s given", arg_num, fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg, given_kind); } + + zend_string_release(need_msg); } else { zend_missing_arg_error(ptr); } } -static int is_null_constant(zend_class_entry *scope, zval *default_value) +static zend_bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg) { - if (Z_TYPE_P(default_value) == IS_CONSTANT_AST) { - zval constant; - - ZVAL_COPY(&constant, default_value); - if (UNEXPECTED(zval_update_constant_ex(&constant, scope) != SUCCESS)) { - return 0; - } - if (Z_TYPE(constant) == IS_NULL) { + zend_long lval; + double dval; + zend_string *str; + zend_bool bval; + + /* Type preference order: int -> float -> string -> bool */ + if (type_mask & MAY_BE_LONG) { + /* For an int|float union type and string value, + * determine chosen type by is_numeric_string() semantics. */ + if ((type_mask & MAY_BE_DOUBLE) && Z_TYPE_P(arg) == IS_STRING) { + zend_uchar type = is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &lval, &dval, -1); + if (type == IS_LONG) { + zend_string_release(Z_STR_P(arg)); + ZVAL_LONG(arg, lval); + return 1; + } + if (type == IS_DOUBLE) { + zend_string_release(Z_STR_P(arg)); + ZVAL_DOUBLE(arg, dval); + return 1; + } + } else if (zend_parse_arg_long_weak(arg, &lval)) { + zval_ptr_dtor(arg); + ZVAL_LONG(arg, lval); return 1; } - zval_ptr_dtor_nogc(&constant); + } + if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval)) { + zval_ptr_dtor(arg); + ZVAL_DOUBLE(arg, dval); + return 1; + } + if ((type_mask & MAY_BE_STRING) && zend_parse_arg_str_weak(arg, &str)) { + /* on success "arg" is converted to IS_STRING */ + return 1; + } + if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval)) { + zval_ptr_dtor(arg); + ZVAL_BOOL(arg, bval); + return 1; } return 0; } -static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg) -{ - switch (type_hint) { - case _IS_BOOL: { - zend_bool dest; - - if (!zend_parse_arg_bool_weak(arg, &dest)) { - return 0; +#if ZEND_DEBUG +/* Used to sanity-check internal arginfo types without performing any actual type conversions. */ +static zend_bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, zval *arg) +{ + zend_long lval; + double dval; + zend_bool bval; + + if (type_mask & MAY_BE_LONG) { + if (Z_TYPE_P(arg) == IS_STRING) { + /* Handle this case separately to avoid the "non well-formed" warning */ + zend_uchar type = is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, &dval, 1); + if (type == IS_LONG) { + return 1; } - zval_ptr_dtor(arg); - ZVAL_BOOL(arg, dest); - return 1; - } - case IS_LONG: { - zend_long dest; + if (type == IS_DOUBLE) { + if ((type_mask & MAY_BE_DOUBLE) + || (!zend_isnan(dval) && ZEND_DOUBLE_FITS_LONG(dval))) { + return 1; + } - if (!zend_parse_arg_long_weak(arg, &dest)) { - return 0; } - zval_ptr_dtor(arg); - ZVAL_LONG(arg, dest); + } + if (zend_parse_arg_long_weak(arg, &lval)) { return 1; } - case IS_DOUBLE: { - double dest; - - if (!zend_parse_arg_double_weak(arg, &dest)) { - return 0; + } + if (type_mask & MAY_BE_DOUBLE) { + if (Z_TYPE_P(arg) == IS_STRING) { + /* Handle this case separately to avoid the "non well-formed" warning */ + if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 1) != 0) { + return 1; } - zval_ptr_dtor(arg); - ZVAL_DOUBLE(arg, dest); - return 1; } - case IS_STRING: { - zend_string *dest; - - /* on success "arg" is converted to IS_STRING */ - return zend_parse_arg_str_weak(arg, &dest); + if (zend_parse_arg_double_weak(arg, &dval)) { + return 1; } - default: - return 0; } + /* We don't call cast_object here, because this check must be side-effect free. As this + * is only used for a sanity check of arginfo/zpp consistency, it's okay if we accept + * more than actually allowed here. */ + if ((type_mask & MAY_BE_STRING) && (Z_TYPE_P(arg) < IS_STRING || Z_TYPE_P(arg) == IS_OBJECT)) { + return 1; + } + if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval)) { + return 1; + } + return 0; } +#endif -static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict) +ZEND_API zend_bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, zend_bool strict, zend_bool is_internal_arg) { if (UNEXPECTED(strict)) { /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */ - if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) { + if (!(type_mask & MAY_BE_DOUBLE) || Z_TYPE_P(arg) != IS_LONG) { return 0; } } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) { - /* NULL may be accepted only by nullable hints (this is already checked) */ - return 0; + /* NULL may be accepted only by nullable hints (this is already checked). + * As an exception for internal functions, null is allowed for scalar types in weak mode. */ + return is_internal_arg + && (type_mask & (MAY_BE_TRUE|MAY_BE_FALSE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING)); + } +#if ZEND_DEBUG + if (is_internal_arg) { + return zend_verify_weak_scalar_type_hint_no_sideeffect(type_mask, arg); } - return zend_verify_weak_scalar_type_hint(type_hint, arg); +#endif + return zend_verify_weak_scalar_type_hint(type_mask, arg); } ZEND_COLD zend_never_inline void zend_verify_property_type_error(zend_property_info *info, zval *property) { - const char *prop_type1, *prop_type2; + zend_string *type_str; /* we _may_ land here in case reading already errored and runtime cache thus has not been updated (i.e. it contains a valid but unrelated info) */ if (EG(exception)) { return; } - // TODO Switch to a more standard error message? - zend_format_type(info->type, &prop_type1, &prop_type2); - (void) prop_type1; - if (ZEND_TYPE_IS_CLASS(info->type)) { - zend_type_error("Typed property %s::$%s must be an instance of %s%s, %s used", - ZSTR_VAL(info->ce->name), - zend_get_unmangled_property_name(info->name), - prop_type2, - ZEND_TYPE_ALLOW_NULL(info->type) ? " or null" : "", - Z_TYPE_P(property) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE_P(property)->name) : zend_get_type_by_const(Z_TYPE_P(property))); - } else { - zend_type_error("Typed property %s::$%s must be %s%s, %s used", - ZSTR_VAL(info->ce->name), - zend_get_unmangled_property_name(info->name), - prop_type2, - ZEND_TYPE_ALLOW_NULL(info->type) ? " or null" : "", - Z_TYPE_P(property) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE_P(property)->name) : zend_get_type_by_const(Z_TYPE_P(property))); - } + type_str = zend_type_to_string(info->type); + zend_type_error("Cannot assign %s to property %s::$%s of type %s", + Z_TYPE_P(property) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE_P(property)->name) : zend_get_type_by_const(Z_TYPE_P(property)), + ZSTR_VAL(info->ce->name), + zend_get_unmangled_property_name(info->name), + ZSTR_VAL(type_str)); + zend_string_release(type_str); } -static zend_bool zend_resolve_class_type(zend_type *type, zend_class_entry *self_ce) { - zend_class_entry *ce; - zend_string *name = ZEND_TYPE_NAME(*type); +static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class_entry *self_ce) { if (zend_string_equals_literal_ci(name, "self")) { /* We need to explicitly check for this here, to avoid updating the type in the trait and * later using the wrong "self" when the trait is used in a class. */ if (UNEXPECTED((self_ce->ce_flags & ZEND_ACC_TRAIT) != 0)) { - zend_throw_error(NULL, "Cannot write a%s value to a 'self' typed static property of a trait", ZEND_TYPE_ALLOW_NULL(*type) ? " non-null" : ""); - return 0; + return NULL; } - ce = self_ce; + return self_ce; } else if (zend_string_equals_literal_ci(name, "parent")) { - if (UNEXPECTED(!self_ce->parent)) { - zend_throw_error(NULL, "Cannot access parent:: when current class scope has no parent"); - return 0; - } - ce = self_ce->parent; + return self_ce->parent; } else { - ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (UNEXPECTED(!ce)) { - return 0; - } + return zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); } - - zend_string_release(name); - *type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type)); - return 1; } +static zend_bool zend_check_and_resolve_property_class_type( + zend_property_info *info, zend_class_entry *object_ce) { + zend_class_entry *ce; + if (ZEND_TYPE_HAS_LIST(info->type)) { + void **entry; + ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(info->type), entry) { + if (ZEND_TYPE_LIST_IS_NAME(*entry)) { + zend_string *name = ZEND_TYPE_LIST_GET_NAME(*entry); + ce = resolve_single_class_type(name, info->ce); + if (!ce) { + continue; + } + zend_string_release(name); + *entry = ZEND_TYPE_LIST_ENCODE_CE(ce); + } else { + ce = ZEND_TYPE_LIST_GET_CE(*entry); + } + if (instanceof_function(object_ce, ce)) { + return 1; + } + } ZEND_TYPE_LIST_FOREACH_END(); + return 0; + } else { + if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) { + zend_string *name = ZEND_TYPE_NAME(info->type); + ce = resolve_single_class_type(name, info->ce); + if (UNEXPECTED(!ce)) { + return 0; + } + + zend_string_release(name); + ZEND_TYPE_SET_CE(info->type, ce); + } else { + ce = ZEND_TYPE_CE(info->type); + } + return instanceof_function(object_ce, ce); + } +} static zend_always_inline zend_bool i_zend_check_property_type(zend_property_info *info, zval *property, zend_bool strict) { ZEND_ASSERT(!Z_ISREF_P(property)); - if (ZEND_TYPE_IS_CLASS(info->type)) { - if (UNEXPECTED(Z_TYPE_P(property) != IS_OBJECT)) { - return Z_TYPE_P(property) == IS_NULL && ZEND_TYPE_ALLOW_NULL(info->type); - } - - if (UNEXPECTED(!ZEND_TYPE_IS_CE(info->type)) && UNEXPECTED(!zend_resolve_class_type(&info->type, info->ce))) { - return 0; - } - - return instanceof_function(Z_OBJCE_P(property), ZEND_TYPE_CE(info->type)); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(info->type, Z_TYPE_P(property)))) { + return 1; } - ZEND_ASSERT(ZEND_TYPE_CODE(info->type) != IS_CALLABLE); - if (EXPECTED(ZEND_TYPE_CODE(info->type) == Z_TYPE_P(property))) { + if (ZEND_TYPE_HAS_CLASS(info->type) && Z_TYPE_P(property) == IS_OBJECT + && zend_check_and_resolve_property_class_type(info, Z_OBJCE_P(property))) { return 1; - } else if (EXPECTED(Z_TYPE_P(property) == IS_NULL)) { - return ZEND_TYPE_ALLOW_NULL(info->type); - } else if (ZEND_TYPE_CODE(info->type) == _IS_BOOL && EXPECTED(Z_TYPE_P(property) == IS_FALSE || Z_TYPE_P(property) == IS_TRUE)) { + } + + ZEND_ASSERT(!(ZEND_TYPE_FULL_MASK(info->type) & MAY_BE_CALLABLE)); + if ((ZEND_TYPE_FULL_MASK(info->type) & MAY_BE_ITERABLE) && zend_is_iterable(property)) { return 1; - } else if (ZEND_TYPE_CODE(info->type) == IS_ITERABLE) { - return zend_is_iterable(property); - } else { - return zend_verify_scalar_type_hint(ZEND_TYPE_CODE(info->type), property, strict); } + return zend_verify_scalar_type_hint(ZEND_TYPE_FULL_MASK(info->type), property, strict, 0); } static zend_bool zend_always_inline i_zend_verify_property_type(zend_property_info *info, zval *property, zend_bool strict) @@ -1011,140 +1027,181 @@ static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *inf return zend_assign_to_variable(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } - -static zend_always_inline zend_bool zend_check_type( - zend_type type, - zval *arg, zend_class_entry **ce, void **cache_slot, - zval *default_value, zend_class_entry *scope, - zend_bool is_return_type) +static zend_always_inline zend_bool zend_check_type_slow( + zend_type type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope, + zend_bool is_return_type, zend_bool is_internal) { - zend_reference *ref = NULL; - - if (!ZEND_TYPE_IS_SET(type)) { - return 1; - } - - if (UNEXPECTED(Z_ISREF_P(arg))) { - ref = Z_REF_P(arg); - arg = Z_REFVAL_P(arg); - } - - if (ZEND_TYPE_IS_CLASS(type)) { - if (EXPECTED(*cache_slot)) { - *ce = (zend_class_entry *) *cache_slot; + uint32_t type_mask; + if (ZEND_TYPE_HAS_CLASS(type) && Z_TYPE_P(arg) == IS_OBJECT) { + zend_class_entry *ce; + if (ZEND_TYPE_HAS_LIST(type)) { + void *entry; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { + if (*cache_slot) { + ce = *cache_slot; + } else { + ce = zend_fetch_class(ZEND_TYPE_LIST_GET_NAME(entry), + (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); + if (!ce) { + cache_slot++; + continue; + } + *cache_slot = ce; + } + if (instanceof_function(Z_OBJCE_P(arg), ce)) { + return 1; + } + cache_slot++; + } ZEND_TYPE_LIST_FOREACH_END(); } else { - *ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); - if (UNEXPECTED(!*ce)) { - return Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value))); + if (EXPECTED(*cache_slot)) { + ce = (zend_class_entry *) *cache_slot; + } else { + ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); + if (UNEXPECTED(!ce)) { + goto builtin_types; + } + *cache_slot = (void *) ce; + } + if (instanceof_function(Z_OBJCE_P(arg), ce)) { + return 1; } - *cache_slot = (void *) *ce; - } - if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { - return instanceof_function(Z_OBJCE_P(arg), *ce); } - return Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value))); - } else if (EXPECTED(ZEND_TYPE_CODE(type) == Z_TYPE_P(arg))) { - return 1; } - if (Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)))) { - /* Null passed to nullable type */ +builtin_types: + type_mask = ZEND_TYPE_FULL_MASK(type); + if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) { return 1; } - - if (ZEND_TYPE_CODE(type) == IS_CALLABLE) { - return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL); - } else if (ZEND_TYPE_CODE(type) == IS_ITERABLE) { - return zend_is_iterable(arg); - } else if (ZEND_TYPE_CODE(type) == _IS_BOOL && - EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) { + if ((type_mask & MAY_BE_ITERABLE) && zend_is_iterable(arg)) { return 1; - } else if (ref && ZEND_REF_HAS_TYPE_SOURCES(ref)) { - return 0; /* we cannot have conversions for typed refs */ - } else { - return zend_verify_scalar_type_hint(ZEND_TYPE_CODE(type), arg, - is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES()); + } + if (ref && ZEND_REF_HAS_TYPE_SOURCES(ref)) { + /* We cannot have conversions for typed refs. */ + return 0; + } + if (is_internal && is_return_type) { + /* For internal returns, the type has to match exactly, because we're not + * going to check it for non-debug builds, and there will be no chance to + * apply coercions. */ + return 0; } + return zend_verify_scalar_type_hint(type_mask, arg, + is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES(), + is_internal); + /* Special handling for IS_VOID is not necessary (for return types), * because this case is already checked at compile-time. */ } -static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot) +static zend_always_inline zend_bool zend_check_type( + zend_type type, zval *arg, void **cache_slot, zend_class_entry *scope, + zend_bool is_return_type, zend_bool is_internal) { - zend_arg_info *cur_arg_info; - zend_class_entry *ce; + zend_reference *ref = NULL; + ZEND_ASSERT(ZEND_TYPE_IS_SET(type)); - if (EXPECTED(arg_num <= zf->common.num_args)) { - cur_arg_info = &zf->common.arg_info[arg_num-1]; - } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) { - cur_arg_info = &zf->common.arg_info[zf->common.num_args]; - } else { - return 1; + if (UNEXPECTED(Z_ISREF_P(arg))) { + ref = Z_REF_P(arg); + arg = Z_REFVAL_P(arg); } - ce = NULL; - if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0))) { - zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg); - return 0; + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(arg)))) { + return 1; } - return 1; + return zend_check_type_slow(type, arg, ref, cache_slot, scope, is_return_type, is_internal); } -static zend_always_inline int zend_verify_recv_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot) +static zend_always_inline int zend_verify_recv_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot) { - zend_arg_info *cur_arg_info = &zf->common.arg_info[arg_num-1]; - zend_class_entry *ce; + zend_arg_info *cur_arg_info; ZEND_ASSERT(arg_num <= zf->common.num_args); cur_arg_info = &zf->common.arg_info[arg_num-1]; - ce = NULL; - if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0))) { - zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg); + if (ZEND_TYPE_IS_SET(cur_arg_info->type) + && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { + zend_verify_arg_error(zf, cur_arg_info, arg_num, cache_slot, arg); return 0; } return 1; } -static zend_always_inline int zend_verify_variadic_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot) +static zend_always_inline int zend_verify_variadic_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot) { zend_arg_info *cur_arg_info; - zend_class_entry *ce; ZEND_ASSERT(arg_num > zf->common.num_args); ZEND_ASSERT(zf->common.fn_flags & ZEND_ACC_VARIADIC); cur_arg_info = &zf->common.arg_info[zf->common.num_args]; - ce = NULL; - if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0))) { - zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg); + if (ZEND_TYPE_IS_SET(cur_arg_info->type) + && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { + zend_verify_arg_error(zf, cur_arg_info, arg_num, cache_slot, arg); return 0; } return 1; } -static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call) +static zend_never_inline ZEND_ATTRIBUTE_UNUSED int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call) { uint32_t i; uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - void *dummy_cache_slot; + zval *arg = ZEND_CALL_ARG(call, 1); for (i = 0; i < num_args; ++i) { - dummy_cache_slot = NULL; - if (UNEXPECTED(!zend_verify_arg_type(fbc, i + 1, p, NULL, &dummy_cache_slot))) { - EG(current_execute_data) = call->prev_execute_data; + zend_arg_info *cur_arg_info; + void *dummy_cache_slot = NULL; + + if (EXPECTED(i < fbc->common.num_args)) { + cur_arg_info = &fbc->common.arg_info[i]; + } else if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_VARIADIC)) { + cur_arg_info = &fbc->common.arg_info[fbc->common.num_args]; + } else { + break; + } + + if (ZEND_TYPE_IS_SET(cur_arg_info->type) + && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &dummy_cache_slot, fbc->common.scope, 0, /* is_internal */ 1))) { return 0; } - p++; + arg++; } return 1; } +#if ZEND_DEBUG +/* Determine whether an internal call should throw, because the passed arguments violate + * an arginfo constraint. This is only checked in debug builds. In release builds, we + * trust that arginfo matches what is enforced by zend_parse_parameters. */ +static zend_always_inline zend_bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_data *call) +{ + if (fbc->common.required_num_args > ZEND_CALL_NUM_ARGS(call)) { + return 1; + } + + if ((fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) && + !zend_verify_internal_arg_types(fbc, call)) { + return 1; + } + + return 0; +} + +static ZEND_COLD void zend_internal_call_arginfo_violation(zend_function *fbc) +{ + zend_error(E_CORE_ERROR, "Arginfo / zpp mismatch during call of %s%s%s()", + fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "", + fbc->common.scope ? "::" : "", + ZSTR_VAL(fbc->common.function_name)); +} +#endif + ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data) { zend_execute_data *ptr = EX(prev_execute_data); @@ -1171,34 +1228,38 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data * } static ZEND_COLD void zend_verify_return_error( - const zend_function *zf, const zend_class_entry *ce, zval *value) + const zend_function *zf, void **cache_slot, zval *value) { const zend_arg_info *arg_info = &zf->common.arg_info[-1]; const char *fname, *fsep, *fclass; - const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind; + zend_string *need_msg; + const char *given_msg, *given_kind; zend_verify_type_error_common( - zf, arg_info, ce, value, - &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind); + zf, arg_info, cache_slot, value, + &fname, &fsep, &fclass, &need_msg, &given_msg, &given_kind); + + zend_type_error("Return value of %s%s%s() must %s, %s%s returned", + fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg, given_kind); - zend_type_error("Return value of %s%s%s() must %s%s%s, %s%s returned", - fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind); + zend_string_release(need_msg); } #if ZEND_DEBUG static ZEND_COLD void zend_verify_internal_return_error( - const zend_function *zf, const zend_class_entry *ce, zval *value) + const zend_function *zf, void **cache_slot, zval *value) { const zend_arg_info *arg_info = &zf->common.arg_info[-1]; const char *fname, *fsep, *fclass; - const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind; + zend_string *need_msg; + const char *given_msg, *given_kind; zend_verify_type_error_common( - zf, arg_info, ce, value, - &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind); + zf, arg_info, cache_slot, value, + &fname, &fsep, &fclass, &need_msg, &given_msg, &given_kind); - zend_error_noreturn(E_CORE_ERROR, "Return value of %s%s%s() must %s%s%s, %s%s returned", - fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind); + zend_error_noreturn(E_CORE_ERROR, "Return value of %s%s%s() must %s, %s%s returned", + fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg, given_kind); } static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, const char *returned_msg, const char *returned_kind) @@ -1222,10 +1283,9 @@ static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, con static int zend_verify_internal_return_type(zend_function *zf, zval *ret) { zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1; - zend_class_entry *ce = NULL; void *dummy_cache_slot = NULL; - if (ZEND_TYPE_CODE(ret_info->type) == IS_VOID) { + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) { if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) { zend_verify_void_return_error(zf, zend_zval_type_name(ret), ""); return 0; @@ -1233,8 +1293,8 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret) return 1; } - if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, &dummy_cache_slot, NULL, NULL, 1))) { - zend_verify_internal_return_error(zf, ce, ret); + if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &dummy_cache_slot, NULL, 1, /* is_internal */ 1))) { + zend_verify_internal_return_error(zf, &dummy_cache_slot, ret); return 0; } @@ -1242,36 +1302,11 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret) } #endif -static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *ret, void **cache_slot) -{ - zend_arg_info *ret_info = zf->common.arg_info - 1; - zend_class_entry *ce = NULL; - - if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, cache_slot, NULL, NULL, 1))) { - zend_verify_return_error(zf, ce, ret); - } -} - static ZEND_COLD int zend_verify_missing_return_type(const zend_function *zf, void **cache_slot) { - zend_arg_info *ret_info = zf->common.arg_info - 1; - - if (ZEND_TYPE_IS_SET(ret_info->type) && UNEXPECTED(ZEND_TYPE_CODE(ret_info->type) != IS_VOID)) { - zend_class_entry *ce = NULL; - if (ZEND_TYPE_IS_CLASS(ret_info->type)) { - if (EXPECTED(*cache_slot)) { - ce = (zend_class_entry*) *cache_slot; - } else { - ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); - if (ce) { - *cache_slot = (void*)ce; - } - } - } - zend_verify_return_error(zf, ce, NULL); - return 0; - } - return 1; + /* VERIFY_RETURN_TYPE is not emitted for "void" functions, so this is always an error. */ + zend_verify_return_error(zf, cache_slot, NULL); + return 0; } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(void) @@ -1281,12 +1316,12 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(v static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_offset(void) { - zend_error(E_WARNING, "Illegal offset type"); + zend_type_error("Illegal offset type"); } static zend_never_inline void zend_assign_to_object_dim(zval *object, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC) { - Z_OBJ_HT_P(object)->write_dimension(object, dim, value); + Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), dim, value); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -1317,25 +1352,15 @@ static zend_always_inline int zend_binary_op(zval *ret, zval *op1, zval *op2 OPL static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC) { - zend_free_op free_op_data1; zval *value; zval *z; zval rv, res; - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); - if ((z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) { - - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + if ((z = Z_OBJ_HT_P(object)->read_dimension(Z_OBJ_P(object), property, BP_VAR_R, &rv)) != NULL) { - if (z == &rv) { - zval_ptr_dtor(&rv); - } - ZVAL_COPY_VALUE(z, value); - } if (zend_binary_op(&res, z, value OPLINE_CC) == SUCCESS) { - Z_OBJ_HT_P(object)->write_dimension(object, property, &res); + Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), property, &res); } if (z == &rv) { zval_ptr_dtor(&rv); @@ -1350,7 +1375,7 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval * ZVAL_NULL(EX_VAR(opline->result.var)); } } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } static zend_never_inline void zend_binary_assign_op_typed_ref(zend_reference *ref, zval *value OPLINE_DC EXECUTE_DATA_DC) @@ -1400,7 +1425,7 @@ try_again: case IS_NULL: case IS_FALSE: case IS_TRUE: - zend_error(E_NOTICE, "String offset cast occurred"); + zend_error(E_WARNING, "String offset cast occurred"); break; case IS_REFERENCE: dim = Z_REFVAL_P(dim); @@ -1530,7 +1555,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_read(z { zend_string *tmp_property_name; zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name); - zend_error(E_NOTICE, "Trying to get property '%s' of non-object", ZSTR_VAL(property_name)); + zend_error(E_WARNING, "Trying to get property '%s' of non-object", ZSTR_VAL(property_name)); zend_tmp_string_release(tmp_property_name); } @@ -1542,12 +1567,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(c ZSTR_VAL(fbc->common.function_name)); } -static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_abstract_method(const zend_function *fbc) -{ - zend_throw_error(NULL, "Cannot call abstract method %s::%s()", - ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); -} - static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC) { zend_uchar c; @@ -1622,50 +1641,51 @@ static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *re { zend_property_info *prop; ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { - if (ZEND_TYPE_CODE(prop->type) != IS_DOUBLE) { + if (!(ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_DOUBLE)) { return prop; } } ZEND_REF_FOREACH_TYPE_SOURCES_END(); return NULL; } -static ZEND_COLD zend_long zend_throw_incdec_ref_error(zend_reference *ref OPLINE_DC) +static ZEND_COLD zend_long zend_throw_incdec_ref_error( + zend_reference *ref, zend_property_info *error_prop OPLINE_DC) { - zend_property_info *error_prop = zend_get_prop_not_accepting_double(ref); - /* Currently there should be no way for a typed reference to accept both int and double. - * Generalize this and the related property code once this becomes possible. */ - ZEND_ASSERT(error_prop); + zend_string *type_str = zend_type_to_string(error_prop->type); if (ZEND_IS_INCREMENT(opline->opcode)) { zend_type_error( - "Cannot increment a reference held by property %s::$%s of type %sint past its maximal value", + "Cannot increment a reference held by property %s::$%s of type %s past its maximal value", ZSTR_VAL(error_prop->ce->name), zend_get_unmangled_property_name(error_prop->name), - ZEND_TYPE_ALLOW_NULL(error_prop->type) ? "?" : ""); + ZSTR_VAL(type_str)); + zend_string_release(type_str); return ZEND_LONG_MAX; } else { zend_type_error( - "Cannot decrement a reference held by property %s::$%s of type %sint past its minimal value", + "Cannot decrement a reference held by property %s::$%s of type %s past its minimal value", ZSTR_VAL(error_prop->ce->name), zend_get_unmangled_property_name(error_prop->name), - ZEND_TYPE_ALLOW_NULL(error_prop->type) ? "?" : ""); + ZSTR_VAL(type_str)); + zend_string_release(type_str); return ZEND_LONG_MIN; } } static ZEND_COLD zend_long zend_throw_incdec_prop_error(zend_property_info *prop OPLINE_DC) { - const char *prop_type1, *prop_type2; - zend_format_type(prop->type, &prop_type1, &prop_type2); + zend_string *type_str = zend_type_to_string(prop->type); if (ZEND_IS_INCREMENT(opline->opcode)) { - zend_type_error("Cannot increment property %s::$%s of type %s%s past its maximal value", + zend_type_error("Cannot increment property %s::$%s of type %s past its maximal value", ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name), - prop_type1, prop_type2); + ZSTR_VAL(type_str)); + zend_string_release(type_str); return ZEND_LONG_MAX; } else { - zend_type_error("Cannot decrement property %s::$%s of type %s%s past its minimal value", + zend_type_error("Cannot decrement property %s::$%s of type %s past its minimal value", ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name), - prop_type1, prop_type2); + ZSTR_VAL(type_str)); + zend_string_release(type_str); return ZEND_LONG_MIN; } } @@ -1688,8 +1708,11 @@ static void zend_incdec_typed_ref(zend_reference *ref, zval *copy OPLINE_DC EXEC } if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(copy) == IS_LONG) { - zend_long val = zend_throw_incdec_ref_error(ref OPLINE_CC); - ZVAL_LONG(var_ptr, val); + zend_property_info *error_prop = zend_get_prop_not_accepting_double(ref); + if (UNEXPECTED(error_prop)) { + zend_long val = zend_throw_incdec_ref_error(ref, error_prop OPLINE_CC); + ZVAL_LONG(var_ptr, val); + } } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) { zval_ptr_dtor(var_ptr); ZVAL_COPY_VALUE(var_ptr, copy); @@ -1716,8 +1739,10 @@ static void zend_incdec_typed_prop(zend_property_info *prop_info, zval *var_ptr, } if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(copy) == IS_LONG) { - zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC); - ZVAL_LONG(var_ptr, val); + if (!(ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_DOUBLE)) { + zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC); + ZVAL_LONG(var_ptr, val); + } } else if (UNEXPECTED(!zend_verify_property_type(prop_info, var_ptr, EX_USES_STRICT_TYPES()))) { zval_ptr_dtor(var_ptr); ZVAL_COPY_VALUE(var_ptr, copy); @@ -1735,7 +1760,8 @@ static void zend_pre_incdec_property_zval(zval *prop, zend_property_info *prop_i } else { fast_long_decrement_function(prop); } - if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && UNEXPECTED(prop_info)) { + if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && UNEXPECTED(prop_info) + && !(ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_DOUBLE)) { zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC); ZVAL_LONG(prop, val); } @@ -1773,7 +1799,8 @@ static void zend_post_incdec_property_zval(zval *prop, zend_property_info *prop_ } else { fast_long_decrement_function(prop); } - if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && UNEXPECTED(prop_info)) { + if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && UNEXPECTED(prop_info) + && !(ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_DOUBLE)) { zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC); ZVAL_LONG(prop, val); } @@ -1800,30 +1827,20 @@ static void zend_post_incdec_property_zval(zval *prop, zend_property_info *prop_ } } -static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_post_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot OPLINE_DC EXECUTE_DATA_DC) { - zval rv, obj; + zval rv; zval *z; zval z_copy; - ZVAL_OBJ(&obj, Z_OBJ_P(object)); - Z_ADDREF(obj); - z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv); + GC_ADDREF(object); + z =object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv); if (UNEXPECTED(EG(exception))) { - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); ZVAL_UNDEF(EX_VAR(opline->result.var)); return; } - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); - if (z == &rv) { - zval_ptr_dtor(&rv); - } - ZVAL_COPY_VALUE(z, value); - } - ZVAL_COPY_DEREF(&z_copy, z); ZVAL_COPY(EX_VAR(opline->result.var), &z_copy); if (ZEND_IS_INCREMENT(opline->opcode)) { @@ -1831,38 +1848,28 @@ static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, } else { decrement_function(&z_copy); } - Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot); - OBJ_RELEASE(Z_OBJ(obj)); + object->handlers->write_property(object, name, &z_copy, cache_slot); + OBJ_RELEASE(object); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } -static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_pre_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot OPLINE_DC EXECUTE_DATA_DC) { zval rv; - zval *z, obj; + zval *z; zval z_copy; - ZVAL_OBJ(&obj, Z_OBJ_P(object)); - Z_ADDREF(obj); - z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv); + GC_ADDREF(object); + z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv); if (UNEXPECTED(EG(exception))) { - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } return; } - if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { - zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); - - if (z == &rv) { - zval_ptr_dtor(&rv); - } - ZVAL_COPY_VALUE(z, value); - } ZVAL_COPY_DEREF(&z_copy, z); if (ZEND_IS_INCREMENT(opline->opcode)) { increment_function(&z_copy); @@ -1872,45 +1879,35 @@ static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), &z_copy); } - Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot); - OBJ_RELEASE(Z_OBJ(obj)); + object->handlers->write_property(object, name, &z_copy, cache_slot); + OBJ_RELEASE(object); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } -static zend_never_inline void zend_assign_op_overloaded_property(zval *object, zval *property, void **cache_slot, zval *value OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_assign_op_overloaded_property(zend_object *object, zend_string *name, void **cache_slot, zval *value OPLINE_DC EXECUTE_DATA_DC) { zval *z; - zval rv, obj, res; + zval rv, res; - ZVAL_OBJ(&obj, Z_OBJ_P(object)); - Z_ADDREF(obj); - z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv); + GC_ADDREF(object); + z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv); if (UNEXPECTED(EG(exception))) { - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } return; } - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); - - if (z == &rv) { - zval_ptr_dtor(&rv); - } - ZVAL_COPY_VALUE(z, value); - } if (zend_binary_op(&res, z, value OPLINE_CC) == SUCCESS) { - Z_OBJ_HT(obj)->write_property(&obj, property, &res, cache_slot); + object->handlers->write_property(object, name, &res, cache_slot); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), &res); } zval_ptr_dtor(z); zval_ptr_dtor(&res); - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); } /* Utility Functions for Extensions */ @@ -1976,16 +1973,10 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_invalid_method_call(z static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_non_static_method_call(const zend_function *fbc) { - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, - "Non-static method %s::%s() should not be called statically", - ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); - } else { - zend_throw_error( - zend_ce_error, - "Non-static method %s::%s() cannot be called statically", - ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); - } + zend_throw_error( + zend_ce_error, + "Non-static method %s::%s() cannot be called statically", + ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num) @@ -1999,17 +1990,17 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(con static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_scalar_as_array(void) { - zend_error(E_WARNING, "Cannot use a scalar value as an array"); + zend_throw_error(NULL, "Cannot use a scalar value as an array"); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void) { - zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied"); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim) { - zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim)); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim)); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_string(void) @@ -2019,8 +2010,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_s static ZEND_COLD void zend_binary_assign_op_dim_slow(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC) { - zend_free_op free_op_data1; - if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { if (opline->op2_type == IS_UNUSED) { zend_use_new_element_for_string(); @@ -2028,11 +2017,10 @@ static ZEND_COLD void zend_binary_assign_op_dim_slow(zval *container, zval *dim zend_check_string_offset(dim, BP_VAR_RW EXECUTE_DATA_CC); zend_wrong_string_offset(EXECUTE_DATA_C); } - } else if (EXPECTED(!Z_ISERROR_P(container))) { + } else { zend_use_scalar_as_array(); } - get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } static zend_never_inline zend_uchar slow_index_convert(const zval *dim, zend_value *value EXECUTE_DATA_DC) @@ -2194,13 +2182,13 @@ fetch_from_array: retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); if (UNEXPECTED(retval == NULL)) { zend_cannot_add_element(); - ZVAL_ERROR(result); + ZVAL_UNDEF(result); return; } } else { retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC); if (UNEXPECTED(!retval)) { - ZVAL_ERROR(result); + ZVAL_UNDEF(result); return; } } @@ -2215,7 +2203,7 @@ fetch_from_array: if (type != BP_VAR_UNSET) { if (ZEND_REF_HAS_TYPE_SOURCES(ref)) { if (UNEXPECTED(!zend_verify_ref_array_assignable(ref))) { - ZVAL_ERROR(result); + ZVAL_UNDEF(result); return; } } @@ -2233,7 +2221,7 @@ fetch_from_array: zend_check_string_offset(dim, type EXECUTE_DATA_CC); zend_wrong_string_offset(EXECUTE_DATA_C); } - ZVAL_ERROR(result); + ZVAL_UNDEF(result); } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { dim = ZVAL_UNDEFINED_OP2(); @@ -2241,7 +2229,7 @@ fetch_from_array: if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result); + retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, type, result); if (UNEXPECTED(retval == &EG(uninitialized_zval))) { zend_class_entry *ce = Z_OBJCE_P(container); @@ -2265,7 +2253,8 @@ fetch_from_array: ZVAL_INDIRECT(result, retval); } } else { - ZVAL_ERROR(result); + ZEND_ASSERT(EG(exception) && "read_dimension() returned NULL without exception"); + ZVAL_UNDEF(result); } } else { if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { @@ -2283,15 +2272,13 @@ return_null: } ZVAL_NULL(result); } - } else if (EXPECTED(Z_ISERROR_P(container))) { - ZVAL_ERROR(result); } else { if (type == BP_VAR_UNSET) { - zend_error(E_WARNING, "Cannot unset offset in a non-array variable"); - ZVAL_NULL(result); + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + ZVAL_UNDEF(result); } else { zend_use_scalar_as_array(); - ZVAL_ERROR(result); + ZVAL_UNDEF(result); } } } @@ -2356,7 +2343,7 @@ try_string_offset: case IS_FALSE: case IS_TRUE: if (type != BP_VAR_IS) { - zend_error(E_NOTICE, "String offset cast occurred"); + zend_error(E_WARNING, "String offset cast occurred"); } break; case IS_REFERENCE: @@ -2374,7 +2361,7 @@ try_string_offset: if (UNEXPECTED(Z_STRLEN_P(container) < (size_t)((offset < 0) ? -offset : (offset + 1)))) { if (type != BP_VAR_IS) { - zend_error(E_NOTICE, "Uninitialized string offset: " ZEND_LONG_FMT, offset); + zend_error(E_WARNING, "Uninitialized string offset: " ZEND_LONG_FMT, offset); ZVAL_EMPTY_STRING(result); } else { ZVAL_NULL(result); @@ -2396,7 +2383,7 @@ try_string_offset: if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result); + retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, type, result); ZEND_ASSERT(result != NULL); if (retval) { @@ -2416,7 +2403,7 @@ try_string_offset: ZVAL_UNDEFINED_OP2(); } if (!is_list && type != BP_VAR_IS) { - zend_error(E_NOTICE, "Trying to access array offset on value of type %s", + zend_error(E_WARNING, "Trying to access array offset on value of type %s", zend_zval_type_name(container)); } ZVAL_NULL(result); @@ -2470,13 +2457,14 @@ str_idx: hval = 1; goto num_idx; } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); hval = Z_RES_HANDLE_P(offset); goto num_idx; } else if (/*OP2_TYPE == IS_CV &&*/ Z_TYPE_P(offset) == IS_UNDEF) { ZVAL_UNDEFINED_OP2(); goto str_idx; } else { - zend_error(E_WARNING, "Illegal offset type in isset or empty"); + zend_type_error("Illegal offset type in isset or empty"); return NULL; } } @@ -2488,7 +2476,7 @@ static zend_never_inline int ZEND_FASTCALL zend_isset_dim_slow(zval *container, } if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - return Z_OBJ_HT_P(container)->has_dimension(container, offset, 0); + return Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 0); } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zend_long lval; @@ -2527,7 +2515,7 @@ static zend_never_inline int ZEND_FASTCALL zend_isempty_dim_slow(zval *container } if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - return !Z_OBJ_HT_P(container)->has_dimension(container, offset, 1); + return !Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 1); } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zend_long lval; @@ -2559,7 +2547,7 @@ str_offset: } } -static zend_never_inline uint32_t ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline zend_bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC) { zend_string *str; zend_ulong hval; @@ -2571,14 +2559,27 @@ try_again: goto num_key; } str_key: - return zend_hash_find_ind(ht, str) != NULL ? IS_TRUE : IS_FALSE; + return zend_hash_find_ind(ht, str) != NULL; } else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) { hval = Z_LVAL_P(key); num_key: - return zend_hash_index_find(ht, hval) != NULL ? IS_TRUE : IS_FALSE; + return zend_hash_index_find(ht, hval) != NULL; } else if (EXPECTED(Z_ISREF_P(key))) { key = Z_REFVAL_P(key); goto try_again; + } else if (Z_TYPE_P(key) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(key)); + goto num_key; + } else if (Z_TYPE_P(key) == IS_FALSE) { + hval = 0; + goto num_key; + } else if (Z_TYPE_P(key) == IS_TRUE) { + hval = 1; + goto num_key; + } else if (Z_TYPE_P(key) == IS_RESOURCE) { + zend_use_resource_as_offset(key); + hval = Z_RES_HANDLE_P(key); + goto num_key; } else if (Z_TYPE_P(key) <= IS_NULL) { if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); @@ -2586,31 +2587,23 @@ num_key: str = ZSTR_EMPTY_ALLOC(); goto str_key; } else { - zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer"); - return IS_FALSE; + zend_type_error("Illegal offset type"); + return 0; } } -static zend_never_inline uint32_t ZEND_FASTCALL zend_array_key_exists_slow(zval *subject, zval *key OPLINE_DC EXECUTE_DATA_DC) +static ZEND_COLD void ZEND_FASTCALL zend_array_key_exists_error( + zval *subject, zval *key OPLINE_DC EXECUTE_DATA_DC) { - if (EXPECTED(Z_TYPE_P(subject) == IS_OBJECT)) { - zend_error(E_DEPRECATED, "array_key_exists(): " - "Using array_key_exists() on objects is deprecated. " - "Use isset() or property_exists() instead"); - - HashTable *ht = zend_get_properties_for(subject, ZEND_PROP_PURPOSE_ARRAY_CAST); - uint32_t result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); - zend_release_properties(ht); - return result; - } else { - if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - if (UNEXPECTED(Z_TYPE_INFO_P(subject) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); - } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "array_key_exists() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(subject))); - return IS_NULL; + if (Z_TYPE_P(key) == IS_UNDEF) { + ZVAL_UNDEFINED_OP1(); + } + if (Z_TYPE_P(subject) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + if (!EG(exception)) { + zend_type_error("array_key_exists() expects parameter 2 to be array, %s given", + zend_get_type_by_const(Z_TYPE_P(subject))); } } @@ -2619,38 +2612,15 @@ static zend_always_inline zend_bool promotes_to_array(zval *val) { || (Z_ISREF_P(val) && Z_TYPE_P(Z_REFVAL_P(val)) <= IS_FALSE); } -static zend_always_inline zend_bool promotes_to_object(zval *val) { - ZVAL_DEREF(val); - return Z_TYPE_P(val) <= IS_FALSE - || (Z_TYPE_P(val) == IS_STRING && Z_STRLEN_P(val) == 0); -} - static zend_always_inline zend_bool check_type_array_assignable(zend_type type) { - if (!type) { - return 1; - } - return ZEND_TYPE_IS_CODE(type) - && (ZEND_TYPE_CODE(type) == IS_ARRAY || ZEND_TYPE_CODE(type) == IS_ITERABLE); -} - -static zend_always_inline zend_bool check_type_stdClass_assignable(zend_type type) { - if (!type) { + if (!ZEND_TYPE_IS_SET(type)) { return 1; } - if (ZEND_TYPE_IS_CLASS(type)) { - if (ZEND_TYPE_IS_CE(type)) { - return ZEND_TYPE_CE(type) == zend_standard_class_def; - } else { - return zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "stdclass"); - } - } else { - return ZEND_TYPE_CODE(type) == IS_OBJECT; - } + return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0; } -/* Checks whether an array can be assigned to the reference. Returns conflicting property if - * assignment is not possible, NULL otherwise. */ -static zend_never_inline zend_bool zend_verify_ref_array_assignable(zend_reference *ref) { +/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */ +ZEND_API zend_bool zend_verify_ref_array_assignable(zend_reference *ref) { zend_property_info *prop; ZEND_ASSERT(ZEND_REF_HAS_TYPE_SOURCES(ref)); ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { @@ -2662,20 +2632,6 @@ static zend_never_inline zend_bool zend_verify_ref_array_assignable(zend_referen return 1; } -/* Checks whether an stdClass can be assigned to the reference. Returns conflicting property if - * assignment is not possible, NULL otherwise. */ -static zend_never_inline zend_bool zend_verify_ref_stdClass_assignable(zend_reference *ref) { - zend_property_info *prop; - ZEND_ASSERT(ZEND_REF_HAS_TYPE_SOURCES(ref)); - ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { - if (!check_type_stdClass_assignable(prop->type)) { - zend_throw_auto_init_in_ref_error(prop, "stdClass"); - return 0; - } - } ZEND_REF_FOREACH_TYPE_SOURCES_END(); - return 1; -} - static zend_property_info *zend_object_fetch_property_type_info( zend_object *obj, zval *slot) { @@ -2711,21 +2667,6 @@ static zend_never_inline zend_bool zend_handle_fetch_obj_flags( } } break; - case ZEND_FETCH_OBJ_WRITE: - if (promotes_to_object(ptr)) { - if (!prop_info) { - prop_info = zend_object_fetch_property_type_info(obj, ptr); - if (!prop_info) { - break; - } - } - if (!check_type_stdClass_assignable(prop_info->type)) { - zend_throw_auto_init_in_prop_error(prop_info, "stdClass"); - if (result) ZVAL_ERROR(result); - return 0; - } - } - break; case ZEND_FETCH_REF: if (Z_TYPE_P(ptr) != IS_REFERENCE) { if (!prop_info) { @@ -2755,8 +2696,10 @@ static zend_never_inline zend_bool zend_handle_fetch_obj_flags( static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, zend_bool init_undef OPLINE_DC EXECUTE_DATA_DC) { zval *ptr; + zend_object *zobj; + zend_string *name, *tmp_name; - if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { do { if (Z_ISREF_P(container) && Z_TYPE_P(Z_REFVAL_P(container)) == IS_OBJECT) { container = Z_REFVAL_P(container); @@ -2775,17 +2718,16 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c return; } - container = make_real_object(container, prop_ptr OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!container)) { - ZVAL_ERROR(result); - return; - } + zend_throw_non_object_error(container, prop_ptr OPLINE_CC EXECUTE_DATA_CC); + ZVAL_ERROR(result); + return; } while (0); } + + zobj = Z_OBJ_P(container); if (prop_op_type == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) { + EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(container); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { ptr = OBJ_PROP(zobj, prop_offset); @@ -2813,18 +2755,24 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } } - ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot); + + if (prop_op_type == IS_CONST) { + name = Z_STR_P(prop_ptr); + } else { + name = zval_get_tmp_string(prop_ptr, &tmp_name); + } + ptr = zobj->handlers->get_property_ptr_ptr(zobj, name, type, cache_slot); if (NULL == ptr) { - ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result); + ptr = zobj->handlers->read_property(zobj, name, type, cache_slot, result); if (ptr == result) { if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) { ZVAL_UNREF(ptr); } - return; + goto end; } } else if (UNEXPECTED(Z_ISERROR_P(ptr))) { ZVAL_ERROR(result); - return; + goto end; } ZVAL_INDIRECT(result, ptr); @@ -2835,18 +2783,23 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c prop_info = CACHED_PTR_EX(cache_slot + 2); if (prop_info) { if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags))) { - return; + goto end; } } } else { if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, Z_OBJ_P(container), NULL, flags))) { - return; + goto end; } } } if (init_undef && UNEXPECTED(Z_TYPE_P(ptr) == IS_UNDEF)) { ZVAL_NULL(ptr); } + +end: + if (prop_op_type != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } static zend_always_inline void zend_assign_to_property_reference(zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC) @@ -2867,8 +2820,6 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); zval_ptr_dtor(&variable); variable_ptr = &EG(uninitialized_zval); - } else if (/*OP_DATA_TYPE == IS_VAR &&*/ UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (/*OP_DATA_TYPE == IS_VAR &&*/ (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -2924,7 +2875,6 @@ static zend_never_inline void zend_assign_to_property_reference_var_var(zval *co } static zend_never_inline int zend_fetch_static_property_address_ex(zval **retval, zend_property_info **prop_info, uint32_t cache_slot, int fetch_type OPLINE_DC EXECUTE_DATA_DC) { - zend_free_op free_op1; zend_string *name, *tmp_name; zend_class_entry *ce; zend_property_info *property_info; @@ -2966,7 +2916,7 @@ static zend_never_inline int zend_fetch_static_property_address_ex(zval **retval if (EXPECTED(op1_type == IS_CONST)) { name = Z_STR_P(RT_CONSTANT(opline, opline->op1)); } else { - zval *varname = get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + zval *varname = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { name = Z_STR_P(varname); tmp_name = NULL; @@ -2983,9 +2933,7 @@ static zend_never_inline int zend_fetch_static_property_address_ex(zval **retval if (UNEXPECTED(op1_type != IS_CONST)) { zend_tmp_string_release(tmp_name); - if (op1_type != IS_CV) { - zval_ptr_dtor_nogc(free_op1); - } + FREE_OP(op1_type, opline->op1.var); } if (UNEXPECTED(*retval == NULL)) { @@ -3012,7 +2960,8 @@ static zend_always_inline int zend_fetch_static_property_address(zval **retval, property_info = CACHED_PTR(cache_slot + sizeof(void *) * 2); if ((fetch_type == BP_VAR_R || fetch_type == BP_VAR_RW) - && UNEXPECTED(Z_TYPE_P(*retval) == IS_UNDEF) && UNEXPECTED(property_info->type != 0)) { + && UNEXPECTED(Z_TYPE_P(*retval) == IS_UNDEF) + && UNEXPECTED(ZEND_TYPE_IS_SET(property_info->type))) { zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", ZSTR_VAL(property_info->ce->name), zend_get_unmangled_property_name(property_info->name)); @@ -3025,7 +2974,7 @@ static zend_always_inline int zend_fetch_static_property_address(zval **retval, } } - if (flags && property_info->type) { + if (flags && ZEND_TYPE_IS_SET(property_info->type)) { zend_handle_fetch_obj_flags(NULL, *retval, NULL, property_info, flags); } @@ -3037,92 +2986,86 @@ static zend_always_inline int zend_fetch_static_property_address(zval **retval, } ZEND_API ZEND_COLD void zend_throw_ref_type_error_type(zend_property_info *prop1, zend_property_info *prop2, zval *zv) { - const char *prop1_type1, *prop1_type2, *prop2_type1, *prop2_type2; - zend_format_type(prop1->type, &prop1_type1, &prop1_type2); - zend_format_type(prop2->type, &prop2_type1, &prop2_type2); - zend_type_error("Reference with value of type %s held by property %s::$%s of type %s%s is not compatible with property %s::$%s of type %s%s", + zend_string *type1_str = zend_type_to_string(prop1->type); + zend_string *type2_str = zend_type_to_string(prop2->type); + zend_type_error("Reference with value of type %s held by property %s::$%s of type %s is not compatible with property %s::$%s of type %s", Z_TYPE_P(zv) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE_P(zv)->name) : zend_get_type_by_const(Z_TYPE_P(zv)), ZSTR_VAL(prop1->ce->name), zend_get_unmangled_property_name(prop1->name), - prop1_type1, prop1_type2, + ZSTR_VAL(type1_str), ZSTR_VAL(prop2->ce->name), zend_get_unmangled_property_name(prop2->name), - prop2_type1, prop2_type2 + ZSTR_VAL(type2_str) ); + zend_string_release(type1_str); + zend_string_release(type2_str); } ZEND_API ZEND_COLD void zend_throw_ref_type_error_zval(zend_property_info *prop, zval *zv) { - const char *prop_type1, *prop_type2; - zend_format_type(prop->type, &prop_type1, &prop_type2); - zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s%s", + zend_string *type_str = zend_type_to_string(prop->type); + zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s", Z_TYPE_P(zv) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE_P(zv)->name) : zend_get_type_by_const(Z_TYPE_P(zv)), ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name), - prop_type1, prop_type2 + ZSTR_VAL(type_str) ); + zend_string_release(type_str); } ZEND_API ZEND_COLD void zend_throw_conflicting_coercion_error(zend_property_info *prop1, zend_property_info *prop2, zval *zv) { - const char *prop1_type1, *prop1_type2, *prop2_type1, *prop2_type2; - zend_format_type(prop1->type, &prop1_type1, &prop1_type2); - zend_format_type(prop2->type, &prop2_type1, &prop2_type2); - zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s%s and property %s::$%s of type %s%s, as this would result in an inconsistent type conversion", + zend_string *type1_str = zend_type_to_string(prop1->type); + zend_string *type2_str = zend_type_to_string(prop2->type); + zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s and property %s::$%s of type %s, as this would result in an inconsistent type conversion", Z_TYPE_P(zv) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE_P(zv)->name) : zend_get_type_by_const(Z_TYPE_P(zv)), ZSTR_VAL(prop1->ce->name), zend_get_unmangled_property_name(prop1->name), - prop1_type1, prop1_type2, + ZSTR_VAL(type1_str), ZSTR_VAL(prop2->ce->name), zend_get_unmangled_property_name(prop2->name), - prop2_type1, prop2_type2 + ZSTR_VAL(type2_str) ); + zend_string_release(type1_str); + zend_string_release(type2_str); } /* 1: valid, 0: invalid, -1: may be valid after type coercion */ static zend_always_inline int i_zend_verify_type_assignable_zval( - zend_type *type_ptr, zend_class_entry *self_ce, zval *zv, zend_bool strict) { - zend_type type = *type_ptr; - zend_uchar type_code; + zend_property_info *info, zval *zv, zend_bool strict) { + zend_type type = info->type; + uint32_t type_mask; zend_uchar zv_type = Z_TYPE_P(zv); - if (ZEND_TYPE_ALLOW_NULL(type) && zv_type == IS_NULL) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(type, zv_type))) { return 1; } - if (ZEND_TYPE_IS_CLASS(type)) { - if (!ZEND_TYPE_IS_CE(type)) { - if (!zend_resolve_class_type(type_ptr, self_ce)) { - return 0; - } - type = *type_ptr; - } - return zv_type == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), ZEND_TYPE_CE(type)); - } - - type_code = ZEND_TYPE_CODE(type); - if (type_code == zv_type || - (type_code == _IS_BOOL && (zv_type == IS_FALSE || zv_type == IS_TRUE))) { + if (ZEND_TYPE_HAS_CLASS(type) && zv_type == IS_OBJECT + && zend_check_and_resolve_property_class_type(info, Z_OBJCE_P(zv))) { return 1; } - if (type_code == IS_ITERABLE) { + type_mask = ZEND_TYPE_FULL_MASK(type); + ZEND_ASSERT(!(type_mask & MAY_BE_CALLABLE)); + if (type_mask & MAY_BE_ITERABLE) { return zend_is_iterable(zv); } /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */ if (strict) { - if (type_code == IS_DOUBLE && zv_type == IS_LONG) { + if ((type_mask & MAY_BE_DOUBLE) && zv_type == IS_LONG) { return -1; } return 0; } - /* No weak conversions for arrays and objects */ - if (type_code == IS_ARRAY || type_code == IS_OBJECT) { + /* NULL may be accepted only by nullable hints (this is already checked) */ + if (zv_type == IS_NULL) { return 0; } - /* NULL may be accepted only by nullable hints (this is already checked) */ - if (zv_type == IS_NULL) { + /* Does not contain any type to which a coercion is possible */ + if (!(type_mask & (MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING)) + && (type_mask & MAY_BE_BOOL) != MAY_BE_BOOL) { return 0; } @@ -3135,37 +3078,62 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference zend_property_info *prop; /* The value must satisfy each property type, and coerce to the same value for each property - * type. Right now, the latter rule means that *if* coercion is necessary, then all types - * must be the same (modulo nullability). To handle this, remember the first type we see and - * compare against it when coercion becomes necessary. */ - zend_property_info *seen_prop = NULL; - zend_uchar seen_type; - zend_bool needs_coercion = 0; + * type. Remember the first coerced type and value we've seen for this purpose. */ + zend_property_info *first_prop = NULL; + zval coerced_value; + ZVAL_UNDEF(&coerced_value); ZEND_ASSERT(Z_TYPE_P(zv) != IS_REFERENCE); ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { - int result = i_zend_verify_type_assignable_zval(&prop->type, prop->ce, zv, strict); + int result = i_zend_verify_type_assignable_zval(prop, zv, strict); if (result == 0) { +type_error: zend_throw_ref_type_error_zval(prop, zv); + zval_ptr_dtor(&coerced_value); return 0; } if (result < 0) { - needs_coercion = 1; - } - - if (!seen_prop) { - seen_prop = prop; - seen_type = ZEND_TYPE_IS_CLASS(prop->type) ? IS_OBJECT : ZEND_TYPE_CODE(prop->type); - } else if (needs_coercion && seen_type != ZEND_TYPE_CODE(prop->type)) { - zend_throw_conflicting_coercion_error(seen_prop, prop, zv); - return 0; + if (!first_prop) { + first_prop = prop; + ZVAL_COPY(&coerced_value, zv); + if (!zend_verify_weak_scalar_type_hint( + ZEND_TYPE_FULL_MASK(prop->type), &coerced_value)) { + goto type_error; + } + } else if (Z_ISUNDEF(coerced_value)) { + /* A previous property did not require coercion, but this one does, + * so they are incompatible. */ + goto conflicting_coercion_error; + } else { + zval tmp; + ZVAL_COPY(&tmp, zv); + if (!zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop->type), &tmp)) { + zval_ptr_dtor(&tmp); + goto type_error; + } + if (!zend_is_identical(&coerced_value, &tmp)) { + zval_ptr_dtor(&tmp); + goto conflicting_coercion_error; + } + } + } else { + if (!first_prop) { + first_prop = prop; + } else if (!Z_ISUNDEF(coerced_value)) { + /* A previous property required coercion, but this one doesn't, + * so they are incompatible. */ +conflicting_coercion_error: + zend_throw_conflicting_coercion_error(first_prop, prop, zv); + zval_ptr_dtor(&coerced_value); + return 0; + } } } ZEND_REF_FOREACH_TYPE_SOURCES_END(); - if (UNEXPECTED(needs_coercion && !zend_verify_weak_scalar_type_hint(seen_type, zv))) { - zend_throw_ref_type_error_zval(seen_prop, zv); - return 0; + if (!Z_ISUNDEF(coerced_value)) { + zval_ptr_dtor(zv); + ZVAL_COPY_VALUE(zv, &coerced_value); } return 1; @@ -3219,21 +3187,23 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_propert int result; val = Z_REFVAL_P(val); - result = i_zend_verify_type_assignable_zval(&prop_info->type, prop_info->ce, val, strict); + result = i_zend_verify_type_assignable_zval(prop_info, val, strict); if (result > 0) { return 1; } if (result < 0) { - zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val)); - if (ZEND_TYPE_CODE(prop_info->type) != ZEND_TYPE_CODE(ref_prop->type)) { - /* Invalid due to conflicting coercion */ + /* This is definitely an error, but we still need to determined why: Either because + * the value is simply illegal for the type, or because or a conflicting coercion. */ + zval tmp; + ZVAL_COPY(&tmp, val); + if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop_info->type), &tmp)) { + zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val)); zend_throw_ref_type_error_type(ref_prop, prop_info, val); + zval_ptr_dtor(&tmp); return 0; } - if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_CODE(prop_info->type), val)) { - return 1; - } + zval_ptr_dtor(&tmp); } } else { ZVAL_DEREF(val); @@ -3316,7 +3286,7 @@ static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DAT Z_ADDREF_P(result); } else { ZVAL_NULL(result); - zend_error(E_NOTICE,"Undefined variable: this"); + zend_error(E_WARNING, "Undefined variable: this"); } break; case BP_VAR_IS: @@ -3928,7 +3898,8 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, } } else if (kind == ZEND_LIVE_SILENCE) { /* restore previous error_reporting value */ - if (!EG(error_reporting) && Z_LVAL_P(var) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(var))) { EG(error_reporting) = Z_LVAL_P(var); } } @@ -4004,9 +3975,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - return NULL; - } + return NULL; } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -4037,7 +4006,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s } /* }}} */ -static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *function, uint32_t num_args) /* {{{ */ +static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_object *function, uint32_t num_args) /* {{{ */ { zend_function *fbc; void *object_or_called_scope; @@ -4045,8 +4014,8 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval * zend_object *object; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; - if (EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)) && - EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)(function, &called_scope, &fbc, &object) == SUCCESS)) { + if (EXPECTED(function->handlers->get_closure) && + EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object, 0) == SUCCESS)) { object_or_called_scope = called_scope; if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { @@ -4128,9 +4097,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - return NULL; - } + return NULL; } object_or_called_scope = called_scope; } else { @@ -4260,43 +4227,6 @@ already_compiled: } /* }}} */ -static ZEND_COLD int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret) /* {{{ */ -{ - zend_function *fbc = call->func; - zend_object *object; - - /* Not sure what should be done here if it's a static method */ - if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) { - zend_vm_stack_free_args(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(fbc->common.function_name, 0); - } - efree(fbc); - zend_vm_stack_free_call_frame(call); - - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - return 0; - } - - object = Z_OBJ(call->This); - - ZVAL_NULL(ret); - - EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, ret); - EG(current_execute_data) = call->prev_execute_data; - - zend_vm_stack_free_args(call); - - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(fbc->common.function_name, 0); - } - efree(fbc); - - return 1; -} -/* }}} */ - static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(array_ptr); @@ -4344,96 +4274,30 @@ static zend_always_inline int _zend_quick_get_constant( const zval *key, uint32_t flags, int check_defined_only OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ { zval *zv; - const zval *orig_key = key; zend_constant *c = NULL; + /* null/true/false are resolved during compilation, so don't check for them here. */ zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); if (zv) { c = (zend_constant*)Z_PTR_P(zv); - } else { + } else if (flags & IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE) { key++; zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) { + if (zv) { c = (zend_constant*)Z_PTR_P(zv); - } else { - if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { - key++; - zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv) { - c = (zend_constant*)Z_PTR_P(zv); - } else { - key++; - zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) { - c = (zend_constant*)Z_PTR_P(zv); - } - } - } } } if (!c) { if (!check_defined_only) { - if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) { - char *actual = (char *)zend_memrchr(Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)), '\\', Z_STRLEN_P(RT_CONSTANT(opline, opline->op2))); - if (!actual) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(RT_CONSTANT(opline, opline->op2))); - } else { - actual++; - ZVAL_STRINGL(EX_VAR(opline->result.var), - actual, Z_STRLEN_P(RT_CONSTANT(opline, opline->op2)) - (actual - Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)))); - } - /* non-qualified constant - allow text substitution */ - zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", - Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); - } else { - zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } + zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } return FAILURE; } if (!check_defined_only) { ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); - if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST))) { - const char *ns_sep; - size_t shortname_offset; - size_t shortname_len; - zend_bool is_deprecated; - - if (flags & IS_CONSTANT_UNQUALIFIED) { - const zval *access_key; - - if (!(flags & IS_CONSTANT_IN_NAMESPACE)) { - access_key = orig_key - 1; - } else { - if (key < orig_key + 2) { - goto check_short_name; - } else { - access_key = orig_key + 2; - } - } - is_deprecated = !zend_string_equals(c->name, Z_STR_P(access_key)); - } else { -check_short_name: - ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name)); - ZEND_ASSERT(ns_sep); - /* Namespaces are always case-insensitive. Only compare shortname. */ - shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1; - shortname_len = ZSTR_LEN(c->name) - shortname_offset; - - is_deprecated = memcmp(ZSTR_VAL(c->name) + shortname_offset, Z_STRVAL_P(orig_key - 1) + shortname_offset, shortname_len) != 0; - } - - if (is_deprecated) { - zend_error(E_DEPRECATED, - "Case-insensitive constants are deprecated. " - "The correct casing for this constant is \"%s\"", - ZSTR_VAL(c->name)); - return SUCCESS; - } - } } CACHE_PTR(opline->extended_value, c); @@ -4501,68 +4365,68 @@ static zend_never_inline int ZEND_FASTCALL zend_quick_check_constant( OPLINE++ -#ifndef VM_SMART_OPCODES -# define VM_SMART_OPCODES 1 -#endif - -#if VM_SMART_OPCODES -# define ZEND_VM_REPEATABLE_OPCODE \ +#define ZEND_VM_REPEATABLE_OPCODE \ do { -# define ZEND_VM_REPEAT_OPCODE(_opcode) \ +#define ZEND_VM_REPEAT_OPCODE(_opcode) \ } while (UNEXPECTED((++opline)->opcode == _opcode)); \ OPLINE = opline; \ ZEND_VM_CONTINUE() -# define ZEND_VM_SMART_BRANCH(_result, _check) do { \ +#define ZEND_VM_SMART_BRANCH(_result, _check) do { \ if ((_check) && UNEXPECTED(EG(exception))) { \ - break; \ - } \ - if (EXPECTED((opline+1)->opcode == ZEND_JMPZ)) { \ + OPLINE = EX(opline); \ + } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \ if (_result) { \ ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ } else { \ ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ } \ - } else if (EXPECTED((opline+1)->opcode == ZEND_JMPNZ)) { \ + } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \ if (!(_result)) { \ ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ } else { \ ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ } \ } else { \ - break; \ + ZVAL_BOOL(EX_VAR(opline->result.var), _result); \ + ZEND_VM_SET_NEXT_OPCODE(opline + 1); \ } \ ZEND_VM_CONTINUE(); \ } while (0) -# define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) do { \ +#define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) do { \ if ((_check) && UNEXPECTED(EG(exception))) { \ - break; \ - } \ - if (_result) { \ + OPLINE = EX(opline); \ + } else if (_result) { \ ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ } else { \ ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ } \ ZEND_VM_CONTINUE(); \ } while (0) -# define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) do { \ +#define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) do { \ if ((_check) && UNEXPECTED(EG(exception))) { \ - break; \ - } \ - if (!(_result)) { \ + OPLINE = EX(opline); \ + } else if (!(_result)) { \ ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ } else { \ ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ } \ ZEND_VM_CONTINUE(); \ } while (0) +#define ZEND_VM_SMART_BRANCH_NONE(_result, _check) do { \ + ZVAL_BOOL(EX_VAR(opline->result.var), _result); \ + ZEND_VM_NEXT_OPCODE_EX(_check, 1); \ + ZEND_VM_CONTINUE(); \ + } while (0) #define ZEND_VM_SMART_BRANCH_TRUE() do { \ - if (EXPECTED((opline+1)->opcode == ZEND_JMPNZ)) { \ + if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \ ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ - ZEND_VM_CONTINUE(); \ - } else if (EXPECTED((opline+1)->opcode == ZEND_JMPZ)) { \ + } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \ ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ - ZEND_VM_CONTINUE(); \ + } else { \ + ZVAL_TRUE(EX_VAR(opline->result.var)); \ + ZEND_VM_SET_NEXT_OPCODE(opline + 1); \ } \ + ZEND_VM_CONTINUE(); \ } while (0) #define ZEND_VM_SMART_BRANCH_TRUE_JMPZ() do { \ ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ @@ -4572,14 +4436,20 @@ static zend_never_inline int ZEND_FASTCALL zend_quick_check_constant( ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ ZEND_VM_CONTINUE(); \ } while (0) +#define ZEND_VM_SMART_BRANCH_TRUE_NONE() do { \ + ZVAL_TRUE(EX_VAR(opline->result.var)); \ + ZEND_VM_NEXT_OPCODE(); \ + } while (0) #define ZEND_VM_SMART_BRANCH_FALSE() do { \ - if (EXPECTED((opline+1)->opcode == ZEND_JMPNZ)) { \ + if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \ ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ - ZEND_VM_CONTINUE(); \ - } else if (EXPECTED((opline+1)->opcode == ZEND_JMPZ)) { \ + } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \ ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ - ZEND_VM_CONTINUE(); \ + } else { \ + ZVAL_FALSE(EX_VAR(opline->result.var)); \ + ZEND_VM_SET_NEXT_OPCODE(opline + 1); \ } \ + ZEND_VM_CONTINUE(); \ } while (0) #define ZEND_VM_SMART_BRANCH_FALSE_JMPZ() do { \ ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \ @@ -4589,15 +4459,10 @@ static zend_never_inline int ZEND_FASTCALL zend_quick_check_constant( ZEND_VM_SET_NEXT_OPCODE(opline + 2); \ ZEND_VM_CONTINUE(); \ } while (0) -#else -# define ZEND_VM_REPEATABLE_OPCODE -# define ZEND_VM_REPEAT_OPCODE(_opcode) -# define ZEND_VM_SMART_BRANCH(_result, _check) -# define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) -# define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) -# define ZEND_VM_SMART_BRANCH_TRUE() -# define ZEND_VM_SMART_BRANCH_FALSE() -#endif +#define ZEND_VM_SMART_BRANCH_FALSE_NONE() do { \ + ZVAL_FALSE(EX_VAR(opline->result.var)); \ + ZEND_VM_NEXT_OPCODE(); \ + } while (0) #ifdef __GNUC__ # define ZEND_VM_GUARD(name) __asm__("#" #name) @@ -4633,27 +4498,21 @@ ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) return zend_user_opcode_handlers[opcode]; } -ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type) +ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data, int type) { zval *ret; switch (op_type) { case IS_CONST: ret = RT_CONSTANT(opline, *node); - *should_free = NULL; break; case IS_TMP_VAR: case IS_VAR: - ret = EX_VAR(node->var); - *should_free = ret; - break; case IS_CV: ret = EX_VAR(node->var); - *should_free = NULL; break; default: ret = NULL; - *should_free = ret; break; } return ret; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index cb100f55e9..70f91ad66f 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -44,10 +44,10 @@ ZEND_API zend_class_entry *zend_lookup_class(zend_string *name); ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags); ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex); ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex); -ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name); -ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name); -ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions); -ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions); +ZEND_API int zend_eval_string(const char *str, zval *retval_ptr, const char *string_name); +ZEND_API int zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name); +ZEND_API int zend_eval_string_ex(const char *str, zval *retval_ptr, const char *string_name, int handle_exceptions); +ZEND_API int zend_eval_stringl_ex(const char *str, size_t str_len, zval *retval_ptr, const char *string_name, int handle_exceptions); /* export zend_pass_function to allow comparisons against it */ extern ZEND_API const zend_internal_function zend_pass_function; @@ -60,6 +60,12 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_propert ZEND_API ZEND_COLD void zend_throw_ref_type_error_zval(zend_property_info *prop, zval *zv); ZEND_API ZEND_COLD void zend_throw_ref_type_error_type(zend_property_info *prop1, zend_property_info *prop2, zval *zv); +ZEND_API zend_bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, zend_bool strict, zend_bool is_internal_arg); +ZEND_API ZEND_COLD void zend_verify_arg_error( + const zend_function *zf, const zend_arg_info *arg_info, + int arg_num, void **cache_slot, zval *value); +ZEND_API zend_bool zend_verify_ref_array_assignable(zend_reference *ref); + #define ZEND_REF_TYPE_SOURCES(ref) \ (ref)->sources @@ -120,11 +126,6 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval break; } } - if (Z_TYPE_P(variable_ptr) == IS_OBJECT && - UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) { - Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value); - return variable_ptr; - } garbage = Z_COUNTED_P(variable_ptr); zend_copy_to_variable(variable_ptr, value, value_type, ref); if (GC_DELREF(garbage) == 0) { @@ -328,10 +329,7 @@ ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler); ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode); -/* former zend_execute_locks.h */ -typedef zval* zend_free_op; - -ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type); +ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data, int type); ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table); ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e1001062e5..de6af0e5d5 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -179,8 +179,6 @@ void init_executor(void) /* {{{ */ EG(ht_iterators) = EG(ht_iterators_slots); memset(EG(ht_iterators), 0, sizeof(EG(ht_iterators_slots))); - EG(each_deprecation_thrown) = 0; - EG(persistent_constants_count) = EG(zend_constants)->nNumUsed; EG(persistent_functions_count) = EG(function_table)->nNumUsed; EG(persistent_classes_count) = EG(class_table)->nNumUsed; @@ -568,29 +566,10 @@ ZEND_API ZEND_COLD int zend_use_undefined_constant(zend_string *name, zend_ast_a } else if ((colon = (char*)zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name)))) { zend_throw_error(NULL, "Undefined class constant '%s'", ZSTR_VAL(name)); return FAILURE; - } else if ((attr & IS_CONSTANT_UNQUALIFIED) == 0) { + } else { zend_throw_error(NULL, "Undefined constant '%s'", ZSTR_VAL(name)); return FAILURE; - } else { - char *actual = ZSTR_VAL(name); - size_t actual_len = ZSTR_LEN(name); - char *slash = (char *) zend_memrchr(actual, '\\', actual_len); - - if (slash) { - actual = slash + 1; - actual_len -= (actual - ZSTR_VAL(name)); - } - - zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", actual, actual); - if (EG(exception)) { - return FAILURE; - } else { - zend_string *result_str = zend_string_init(actual, actual_len, 0); - zval_ptr_dtor_nogc(result); - ZVAL_NEW_STR(result, result_str); - } } - return SUCCESS; } /* }}} */ @@ -707,20 +686,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / EG(current_execute_data) = dummy_execute_data.prev_execute_data; } return FAILURE; - } else if (error) { - /* Capitalize the first latter of the error message */ - if (error[0] >= 'a' && error[0] <= 'z') { - error[0] += ('A' - 'a'); - } - zend_error(E_DEPRECATED, "%s", error); - efree(error); - if (UNEXPECTED(EG(exception))) { - if (EG(current_execute_data) == &dummy_execute_data) { - EG(current_execute_data) = dummy_execute_data.prev_execute_data; - } - return FAILURE; - } } + + ZEND_ASSERT(!error); } func = fci_cache->function_handler; @@ -814,8 +782,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / /* We must re-initialize function again */ fci_cache->function_handler = NULL; } - } else if (func->type == ZEND_INTERNAL_FUNCTION) { + } else { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; + + ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION); ZVAL_NULL(fci->retval); call->prev_execute_data = EG(current_execute_data); EG(current_execute_data) = call; @@ -837,30 +807,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / /* We must re-initialize function again */ fci_cache->function_handler = NULL; } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ZVAL_NULL(fci->retval); - - /* Not sure what should be done here if it's a static method */ - if (fci->object) { - call->prev_execute_data = EG(current_execute_data); - EG(current_execute_data) = call; - fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval); - EG(current_execute_data) = call->prev_execute_data; - } else { - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - } - - zend_vm_stack_free_args(call); - - if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(func->common.function_name, 0); - } - efree(func); - - if (EG(exception)) { - zval_ptr_dtor(fci->retval); - ZVAL_UNDEF(fci->retval); - } } zend_vm_stack_free_call_frame(call); @@ -936,16 +882,10 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string * } if (!EG(autoload_func)) { - zend_function *func = zend_fetch_function(ZSTR_KNOWN(ZEND_STR_MAGIC_AUTOLOAD)); - - if (func) { - EG(autoload_func) = func; - } else { - if (!key) { - zend_string_release_ex(lc_name, 0); - } - return NULL; + if (!key) { + zend_string_release_ex(lc_name, 0); } + return NULL; } @@ -1050,7 +990,7 @@ ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */ } /* }}} */ -ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */ +ZEND_API int zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name) /* {{{ */ { zval pv; zend_op_array *new_op_array; @@ -1114,13 +1054,13 @@ ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char } /* }}} */ -ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name) /* {{{ */ +ZEND_API int zend_eval_string(const char *str, zval *retval_ptr, const char *string_name) /* {{{ */ { return zend_eval_stringl(str, strlen(str), retval_ptr, string_name); } /* }}} */ -ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */ +ZEND_API int zend_eval_stringl_ex(const char *str, size_t str_len, zval *retval_ptr, const char *string_name, int handle_exceptions) /* {{{ */ { int result; @@ -1133,7 +1073,7 @@ ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, c } /* }}} */ -ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */ +ZEND_API int zend_eval_string_ex(const char *str, zval *retval_ptr, const char *string_name, int handle_exceptions) /* {{{ */ { return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions); } diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index 19cbf557c5..87c7748c36 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -44,7 +44,7 @@ You can use the following macro to check the extension API version for compatibi /* The first number is the engine version and the rest is the date (YYYYMMDD). * This way engine 2/3 API no. is always greater than engine 1 API no.. */ -#define ZEND_EXTENSION_API_NO 320190902 +#define ZEND_EXTENSION_API_NO 420190128 typedef struct _zend_extension_version_info { int zend_extension_api_no; diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 7cecd53410..30698f4484 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -702,10 +702,8 @@ tail_call: if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) { ht = NULL; @@ -822,10 +820,8 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_GREY))) { ht = NULL; @@ -1008,10 +1004,8 @@ tail_call: if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(!GC_REF_CHECK_COLOR(ht, GC_GREY))) { ht = NULL; @@ -1171,7 +1165,6 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; /* optimization: color is GC_BLACK (0) */ if (!GC_INFO(ref)) { @@ -1182,8 +1175,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta || obj->ce->destructor != NULL)) { *flags |= GC_HAS_DESTRUCTORS; } - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) { ht = NULL; @@ -1357,10 +1349,8 @@ tail_call: if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht)) { if (!n) return count; diff --git a/Zend/zend_gdb.c b/Zend/zend_gdb.c new file mode 100644 index 0000000000..0fff742048 --- /dev/null +++ b/Zend/zend_gdb.c @@ -0,0 +1,141 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov <dmitry@zend.com> | + | Xinchen Hui <xinchen.h@zend.com> | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_gdb.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +enum { + ZEND_GDBJIT_NOACTION, + ZEND_GDBJIT_REGISTER, + ZEND_GDBJIT_UNREGISTER +}; + +typedef struct _zend_gdbjit_code_entry { + struct _zend_gdbjit_code_entry *next_entry; + struct _zend_gdbjit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; +} zend_gdbjit_code_entry; + +typedef struct _zend_gdbjit_descriptor { + uint32_t version; + uint32_t action_flag; + struct _zend_gdbjit_code_entry *relevant_entry; + struct _zend_gdbjit_code_entry *first_entry; +} zend_gdbjit_descriptor; + +ZEND_API zend_gdbjit_descriptor __jit_debug_descriptor = { + 1, ZEND_GDBJIT_NOACTION, NULL, NULL +}; + +ZEND_API zend_never_inline void __jit_debug_register_code() +{ + __asm__ __volatile__(""); +} + +ZEND_API int zend_gdb_register_code(const void *object, size_t size) +{ + zend_gdbjit_code_entry *entry; + + entry = malloc(sizeof(zend_gdbjit_code_entry) + size); + if (entry == NULL) { + return 0; + } + + entry->symfile_addr = ((char*)entry) + sizeof(zend_gdbjit_code_entry); + entry->symfile_size = size; + + memcpy((char *)entry->symfile_addr, object, size); + + entry->prev_entry = NULL; + entry->next_entry = __jit_debug_descriptor.first_entry; + + if (entry->next_entry) { + entry->next_entry->prev_entry = entry; + } + __jit_debug_descriptor.first_entry = entry; + + /* Notify GDB */ + __jit_debug_descriptor.relevant_entry = entry; + __jit_debug_descriptor.action_flag = ZEND_GDBJIT_REGISTER; + __jit_debug_register_code(); + + return 1; +} + +ZEND_API void zend_gdb_unregister_all(void) +{ + zend_gdbjit_code_entry *entry; + + __jit_debug_descriptor.action_flag = ZEND_GDBJIT_UNREGISTER; + while ((entry = __jit_debug_descriptor.first_entry)) { + __jit_debug_descriptor.first_entry = entry->next_entry; + if (entry->next_entry) { + entry->next_entry->prev_entry = NULL; + } + /* Notify GDB */ + __jit_debug_descriptor.relevant_entry = entry; + __jit_debug_register_code(); + + free(entry); + } +} + +ZEND_API int zend_gdb_present(void) +{ + int ret = 0; + int fd = open("/proc/self/status", O_RDONLY); + + if (fd > 0) { + char buf[1024]; + ssize_t n = read(fd, buf, sizeof(buf) - 1); + char *s; + pid_t pid; + + if (n > 0) { + buf[n] = 0; + s = strstr(buf, "TracerPid:"); + if (s) { + s += sizeof("TracerPid:") - 1; + while (*s == ' ' || *s == '\t') { + s++; + } + pid = atoi(s); + if (pid) { + char out[1024]; + sprintf(buf, "/proc/%d/exe", (int)pid); + if (readlink(buf, out, sizeof(out) - 1) > 0) { + if (strstr(out, "gdb")) { + ret = 1; + } + } + } + } + } + + close(fd); + } + + return ret; +} diff --git a/Zend/zend_gdb.h b/Zend/zend_gdb.h new file mode 100644 index 0000000000..220b70888f --- /dev/null +++ b/Zend/zend_gdb.h @@ -0,0 +1,27 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov <dmitry@zend.com> | + | Xinchen Hui <laruence@php.net> | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_GDB +#define ZEND_GDB + +ZEND_API int zend_gdb_register_code(const void *object, size_t size); +ZEND_API void zend_gdb_unregister_all(void); +ZEND_API int zend_gdb_present(void); + +#endif diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 3c75b03004..d086892c3a 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -23,6 +23,7 @@ #include "zend_exceptions.h" #include "zend_generators.h" #include "zend_closures.h" +#include "zend_generators_arginfo.h" ZEND_API zend_class_entry *zend_ce_generator; ZEND_API zend_class_entry *zend_ce_ClosedGeneratorException; @@ -307,9 +308,9 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */ } /* }}} */ -static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {{{ */ +static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int *n) /* {{{ */ { - zend_generator *generator = (zend_generator*) Z_OBJ_P(object); + zend_generator *generator = (zend_generator*)object; zend_execute_data *execute_data = generator->execute_data; zend_op_array *op_array; zval *gc_buffer; @@ -1012,7 +1013,7 @@ ZEND_METHOD(Generator, throw) zend_generator *generator; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ZVAL(exception) + Z_PARAM_OBJECT_OF_CLASS(exception, zend_ce_throwable); ZEND_PARSE_PARAMETERS_END(); Z_TRY_ADDREF_P(exception); @@ -1177,26 +1178,15 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob } /* }}} */ -ZEND_BEGIN_ARG_INFO(arginfo_generator_void, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_send, 0, 0, 1) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_throw, 0, 0, 1) - ZEND_ARG_INFO(0, exception) -ZEND_END_ARG_INFO() - static const zend_function_entry generator_functions[] = { - ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, valid, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, current, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, next, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, send, arginfo_generator_send, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, throw, arginfo_generator_throw, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, getReturn,arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, rewind, arginfo_class_Generator_rewind, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, valid, arginfo_class_Generator_valid, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, current, arginfo_class_Generator_current, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, key, arginfo_class_Generator_key, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, next, arginfo_class_Generator_next, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, send, arginfo_class_Generator_send, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, throw, arginfo_class_Generator_throw, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, getReturn,arginfo_class_Generator_getReturn, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/Zend/zend_generators.stub.php b/Zend/zend_generators.stub.php new file mode 100644 index 0000000000..759bd4cd48 --- /dev/null +++ b/Zend/zend_generators.stub.php @@ -0,0 +1,20 @@ +<?php + +final class Generator implements Iterator +{ + function rewind(): void {} + + function valid(): bool {} + + function current() {} + + function key() {} + + function next(): void {} + + function send($value) {} + + function throw(Throwable $exception) {} + + function getReturn() {} +} diff --git a/Zend/zend_generators_arginfo.h b/Zend/zend_generators_arginfo.h new file mode 100644 index 0000000000..a65d6b1b12 --- /dev/null +++ b/Zend/zend_generators_arginfo.h @@ -0,0 +1,24 @@ +/* This is a generated file, edit the .stub.php file instead. */ + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Generator_rewind, 0, 0, IS_VOID, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Generator_valid, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Generator_current, 0, 0, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Generator_key arginfo_class_Generator_current + +#define arginfo_class_Generator_next arginfo_class_Generator_rewind + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Generator_send, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Generator_throw, 0, 0, 1) + ZEND_ARG_OBJ_INFO(0, exception, Throwable, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Generator_getReturn arginfo_class_Generator_current diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 2e9fff40ad..2dc769a5ef 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -234,8 +234,6 @@ struct _zend_executor_globals { zend_function trampoline; zend_op call_trampoline_op; - zend_bool each_deprecation_thrown; - HashTable weakrefs; zend_bool exception_ignore_args; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index c2c8cf825f..79a2f52d6c 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -234,7 +234,7 @@ static zend_always_inline void _zend_hash_init_int(HashTable *ht, uint32_t nSize ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nInternalPointer = 0; - ht->nNextFreeElement = 0; + ht->nNextFreeElement = ZEND_LONG_MIN; ht->pDestructor = pDestructor; ht->nTableSize = zend_hash_check_size(nSize); } @@ -964,6 +964,10 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); + if ((flag & HASH_ADD_NEXT) && h == ZEND_LONG_MIN) { + h = 0; + } + if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { if (h < ht->nNumUsed) { p = ht->arData + h; @@ -1028,8 +1032,8 @@ convert_to_hash: p = ht->arData + idx; Z_NEXT(p->val) = HT_HASH(ht, nIndex); HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx); - if ((zend_long)h >= (zend_long)ht->nNextFreeElement) { - ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX; + if ((zend_long)h >= ht->nNextFreeElement) { + ht->nNextFreeElement = (zend_long)h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX; } add: ht->nNumOfElements++; @@ -1168,7 +1172,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht) } } -ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht) +ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht) { Bucket *p; uint32_t nIndex, i; @@ -1180,7 +1184,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht) ht->nNumUsed = 0; HT_HASH_RESET(ht); } - return SUCCESS; + return; } HT_HASH_RESET(ht); @@ -1258,7 +1262,6 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht) _zend_hash_iterators_update(ht, old_num_used, ht->nNumUsed); } } - return SUCCESS; } static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev) @@ -1702,7 +1705,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht) } ht->nNumUsed = 0; ht->nNumOfElements = 0; - ht->nNextFreeElement = 0; + ht->nNextFreeElement = ZEND_LONG_MIN; ht->nInternalPointer = 0; } @@ -1741,7 +1744,7 @@ ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht) } ht->nNumUsed = 0; ht->nNumOfElements = 0; - ht->nNextFreeElement = 0; + ht->nNextFreeElement = ZEND_LONG_MIN; ht->nInternalPointer = 0; } @@ -2055,7 +2058,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) target->nTableMask = HT_MIN_MASK; target->nNumUsed = 0; target->nNumOfElements = 0; - target->nNextFreeElement = 0; + target->nNextFreeElement = ZEND_LONG_MIN; target->nInternalPointer = 0; target->nTableSize = HT_MIN_SIZE; HT_SET_DATA_ADDR(target, &uninitialized_bucket); @@ -2465,7 +2468,7 @@ ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q) q->h = h; } -ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber) +ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber) { Bucket *p; uint32_t i, j; @@ -2474,7 +2477,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, co HT_ASSERT_RC1(ht); if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */ - return SUCCESS; + return; } if (HT_IS_WITHOUT_HOLES(ht)) { @@ -2529,8 +2532,6 @@ ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, co zend_hash_rehash(ht); } } - - return SUCCESS; } static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index f1e2d34685..7263c47a82 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -265,7 +265,7 @@ ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q); ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q); ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q); ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered); -ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber); +ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber); ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag); #define zend_hash_sort(ht, compare_func, renumber) \ @@ -277,7 +277,7 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_ #define zend_hash_next_free_element(ht) \ (ht)->nNextFreeElement -ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht); +ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht); #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P) # define zend_new_array(size) \ diff --git a/Zend/zend_highlight.h b/Zend/zend_highlight.h index 92a4dbccd3..8ea1518ca6 100644 --- a/Zend/zend_highlight.h +++ b/Zend/zend_highlight.h @@ -39,8 +39,8 @@ typedef struct _zend_syntax_highlighter_ini { BEGIN_EXTERN_C() ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini); ZEND_API void zend_strip(void); -ZEND_API int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini); -ZEND_API int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name); +ZEND_API int highlight_file(const char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini); +ZEND_API int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, const char *str_name); ZEND_API void zend_html_putc(char c); ZEND_API void zend_html_puts(const char *s, size_t len); END_EXTERN_C() diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 0dbb5b77a6..220df561a2 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -29,8 +29,7 @@ static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce); static void add_compatibility_obligation( - zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn, - zend_bool always_error); + zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn); static void add_property_compatibility_obligation( zend_class_entry *ce, const zend_property_info *child_prop, const zend_property_info *parent_prop); @@ -41,14 +40,31 @@ static void overridden_ptr_dtor(zval *zv) /* {{{ */ } /* }}} */ +static void zend_type_copy_ctor(zend_type *type, zend_bool persistent) { + if (ZEND_TYPE_HAS_LIST(*type)) { + zend_type_list *old_list = ZEND_TYPE_LIST(*type); + size_t size = ZEND_TYPE_LIST_SIZE(old_list->num_types); + zend_type_list *new_list = ZEND_TYPE_USES_ARENA(*type) + ? zend_arena_alloc(&CG(arena), size) : pemalloc(size, persistent); + memcpy(new_list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types)); + ZEND_TYPE_SET_PTR(*type, new_list); + + void *entry; + ZEND_TYPE_LIST_FOREACH(new_list, entry) { + ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + zend_string_addref(ZEND_TYPE_LIST_GET_NAME(entry)); + } ZEND_TYPE_LIST_FOREACH_END(); + } else if (ZEND_TYPE_HAS_NAME(*type)) { + zend_string_addref(ZEND_TYPE_NAME(*type)); + } +} + static zend_property_info *zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */ { zend_property_info* new_property_info = pemalloc(sizeof(zend_property_info), 1); memcpy(new_property_info, property_info, sizeof(zend_property_info)); zend_string_addref(new_property_info->name); - if (ZEND_TYPE_IS_NAME(new_property_info->type)) { - zend_string_addref(ZEND_TYPE_NAME(new_property_info->type)); - } + zend_type_copy_ctor(&new_property_info->type, /* persistent */ 1); return new_property_info; } @@ -220,7 +236,8 @@ static zend_bool class_visible(zend_class_entry *ce) { } } -static zend_class_entry *lookup_class(zend_class_entry *scope, zend_string *name) { +static zend_class_entry *lookup_class( + zend_class_entry *scope, zend_string *name, zend_bool register_unresolved) { zend_class_entry *ce; if (!CG(in_compilation)) { uint32_t flags = ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD; @@ -229,12 +246,14 @@ static zend_class_entry *lookup_class(zend_class_entry *scope, zend_string *name return ce; } - /* We'll autoload this class and process delayed variance obligations later. */ - if (!CG(delayed_autoloads)) { - ALLOC_HASHTABLE(CG(delayed_autoloads)); - zend_hash_init(CG(delayed_autoloads), 0, NULL, NULL, 0); + if (register_unresolved) { + /* We'll autoload this class and process delayed variance obligations later. */ + if (!CG(delayed_autoloads)) { + ALLOC_HASHTABLE(CG(delayed_autoloads)); + zend_hash_init(CG(delayed_autoloads), 0, NULL, NULL, 0); + } + zend_hash_add_empty_element(CG(delayed_autoloads), name); } - zend_hash_add_empty_element(CG(delayed_autoloads), name); } else { ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); if (ce && class_visible(ce)) { @@ -303,6 +322,23 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce return 0; } +static zend_bool zend_type_contains_traversable(zend_type type) { + if (ZEND_TYPE_HAS_LIST(type)) { + void *entry; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { + ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + if (zend_string_equals_literal_ci(ZEND_TYPE_LIST_GET_NAME(entry), "Traversable")) { + return 1; + } + } ZEND_TYPE_LIST_FOREACH_END(); + return 0; + } + if (ZEND_TYPE_HAS_NAME(type)) { + return zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "Traversable"); + } + return 0; +} + /* Unresolved means that class declarations that are currently not available are needed to * determine whether the inheritance is valid or not. At runtime UNRESOLVED should be treated * as an ERROR. */ @@ -312,85 +348,150 @@ typedef enum { INHERITANCE_SUCCESS = 1, } inheritance_status; -static inheritance_status zend_perform_covariant_type_check( - zend_string **unresolved_class, - const zend_function *fe, zend_arg_info *fe_arg_info, - const zend_function *proto, zend_arg_info *proto_arg_info) /* {{{ */ -{ - zend_type fe_type = fe_arg_info->type, proto_type = proto_arg_info->type; - ZEND_ASSERT(ZEND_TYPE_IS_SET(fe_type) && ZEND_TYPE_IS_SET(proto_type)); - - if (ZEND_TYPE_ALLOW_NULL(fe_type) && !ZEND_TYPE_ALLOW_NULL(proto_type)) { - return INHERITANCE_ERROR; +static inheritance_status zend_perform_covariant_class_type_check( + zend_class_entry *fe_scope, zend_string *fe_class_name, + zend_class_entry *proto_scope, zend_type proto_type, + zend_bool register_unresolved) { + zend_bool have_unresolved = 0; + zend_class_entry *fe_ce = NULL; + if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_OBJECT) { + /* Currently, any class name would be allowed here. We still perform a class lookup + * for forward-compatibility reasons, as we may have named types in the future that + * are not classes (such as enums or typedefs). */ + if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); + if (!fe_ce) { + have_unresolved = 1; + } else { + return INHERITANCE_SUCCESS; + } } - - if (ZEND_TYPE_IS_CLASS(proto_type)) { - zend_string *fe_class_name, *proto_class_name; - zend_class_entry *fe_ce, *proto_ce; - if (!ZEND_TYPE_IS_CLASS(fe_type)) { - return INHERITANCE_ERROR; + if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_ITERABLE) { + if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); + if (!fe_ce) { + have_unresolved = 1; + } else if (unlinked_instanceof(fe_ce, zend_ce_traversable)) { + return INHERITANCE_SUCCESS; } - - fe_class_name = resolve_class_name(fe->common.scope, ZEND_TYPE_NAME(fe_type)); - proto_class_name = resolve_class_name(proto->common.scope, ZEND_TYPE_NAME(proto_type)); + } + if (ZEND_TYPE_HAS_NAME(proto_type)) { + zend_string *proto_class_name = resolve_class_name(proto_scope, ZEND_TYPE_NAME(proto_type)); if (zend_string_equals_ci(fe_class_name, proto_class_name)) { return INHERITANCE_SUCCESS; } /* Make sure to always load both classes, to avoid only registering one of them as * a delayed autoload. */ - fe_ce = lookup_class(fe->common.scope, fe_class_name); - proto_ce = lookup_class(proto->common.scope, proto_class_name); - if (!fe_ce) { - *unresolved_class = fe_class_name; - return INHERITANCE_UNRESOLVED; - } - if (!proto_ce) { - *unresolved_class = proto_class_name; - return INHERITANCE_UNRESOLVED; + if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); + zend_class_entry *proto_ce = + lookup_class(proto_scope, proto_class_name, register_unresolved); + if (!fe_ce || !proto_ce) { + have_unresolved = 1; + } else if (unlinked_instanceof(fe_ce, proto_ce)) { + return INHERITANCE_SUCCESS; } + } + if (ZEND_TYPE_HAS_LIST(proto_type)) { + void *entry; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(proto_type), entry) { + ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + zend_string *proto_class_name = + resolve_class_name(proto_scope, ZEND_TYPE_LIST_GET_NAME(entry)); + if (zend_string_equals_ci(fe_class_name, proto_class_name)) { + return INHERITANCE_SUCCESS; + } - return unlinked_instanceof(fe_ce, proto_ce) ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; - } else if (ZEND_TYPE_CODE(proto_type) == IS_ITERABLE) { - if (ZEND_TYPE_IS_CLASS(fe_type)) { - zend_string *fe_class_name = - resolve_class_name(fe->common.scope, ZEND_TYPE_NAME(fe_type)); - zend_class_entry *fe_ce = lookup_class(fe->common.scope, fe_class_name); - if (!fe_ce) { - *unresolved_class = fe_class_name; - return INHERITANCE_UNRESOLVED; + if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); + zend_class_entry *proto_ce = + lookup_class(proto_scope, proto_class_name, register_unresolved); + if (!fe_ce || !proto_ce) { + have_unresolved = 1; + } else if (unlinked_instanceof(fe_ce, proto_ce)) { + return INHERITANCE_SUCCESS; } - return unlinked_instanceof(fe_ce, zend_ce_traversable) - ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; + } ZEND_TYPE_LIST_FOREACH_END(); + } + return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR; +} + +static inheritance_status zend_perform_covariant_type_check( + zend_class_entry *fe_scope, zend_type fe_type, + zend_class_entry *proto_scope, zend_type proto_type) /* {{{ */ +{ + ZEND_ASSERT(ZEND_TYPE_IS_SET(fe_type) && ZEND_TYPE_IS_SET(proto_type)); + + /* Builtin types may be removed, but not added */ + uint32_t fe_type_mask = ZEND_TYPE_PURE_MASK(fe_type); + uint32_t proto_type_mask = ZEND_TYPE_PURE_MASK(proto_type); + uint32_t added_types = fe_type_mask & ~proto_type_mask; + if (added_types) { + // TODO: Make "iterable" an alias of "array|Traversable" instead, + // so these special cases will be handled automatically. + if (added_types == MAY_BE_ITERABLE + && (proto_type_mask & MAY_BE_ARRAY) + && zend_type_contains_traversable(proto_type)) { + /* Replacing array|Traversable with iterable is okay */ + } else if (added_types == MAY_BE_ARRAY && (proto_type_mask & MAY_BE_ITERABLE)) { + /* Replacing iterable with array is okay */ + } else { + /* Otherwise adding new types is illegal */ + return INHERITANCE_ERROR; + } + } + + if (ZEND_TYPE_HAS_NAME(fe_type)) { + zend_string *fe_class_name = resolve_class_name(fe_scope, ZEND_TYPE_NAME(fe_type)); + inheritance_status status = zend_perform_covariant_class_type_check( + fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 0); + if (status != INHERITANCE_UNRESOLVED) { + return status; } - return ZEND_TYPE_CODE(fe_type) == IS_ITERABLE || ZEND_TYPE_CODE(fe_type) == IS_ARRAY - ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; - } else if (ZEND_TYPE_CODE(proto_type) == IS_OBJECT) { - if (ZEND_TYPE_IS_CLASS(fe_type)) { - /* Currently, any class name would be allowed here. We still perform a class lookup - * for forward-compatibility reasons, as we may have named types in the future that - * are not classes (such as enums or typedefs). */ + zend_perform_covariant_class_type_check( + fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 1); + return INHERITANCE_UNRESOLVED; + } + + if (ZEND_TYPE_HAS_LIST(fe_type)) { + void *entry; + zend_bool all_success = 1; + + /* First try to check whether we can succeed without resolving anything */ + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), entry) { + ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); zend_string *fe_class_name = - resolve_class_name(fe->common.scope, ZEND_TYPE_NAME(fe_type)); - zend_class_entry *fe_ce = lookup_class(fe->common.scope, fe_class_name); - if (!fe_ce) { - *unresolved_class = fe_class_name; - return INHERITANCE_UNRESOLVED; + resolve_class_name(fe_scope, ZEND_TYPE_LIST_GET_NAME(entry)); + inheritance_status status = zend_perform_covariant_class_type_check( + fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 0); + if (status == INHERITANCE_ERROR) { + return INHERITANCE_ERROR; } + + if (status != INHERITANCE_SUCCESS) { + all_success = 0; + } + } ZEND_TYPE_LIST_FOREACH_END(); + + /* All individual checks suceeded, overall success */ + if (all_success) { return INHERITANCE_SUCCESS; } - return ZEND_TYPE_CODE(fe_type) == IS_OBJECT ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; - } else { - return ZEND_TYPE_CODE(fe_type) == ZEND_TYPE_CODE(proto_type) - ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; + /* Register all classes that may have to be resolved */ + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), entry) { + ZEND_ASSERT(ZEND_TYPE_LIST_IS_NAME(entry)); + zend_string *fe_class_name = + resolve_class_name(fe_scope, ZEND_TYPE_LIST_GET_NAME(entry)); + zend_perform_covariant_class_type_check( + fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 1); + } ZEND_TYPE_LIST_FOREACH_END(); + return INHERITANCE_UNRESOLVED; } + + return INHERITANCE_SUCCESS; } /* }}} */ static inheritance_status zend_do_perform_arg_type_hint_check( - zend_string **unresolved_class, const zend_function *fe, zend_arg_info *fe_arg_info, const zend_function *proto, zend_arg_info *proto_arg_info) /* {{{ */ { @@ -407,12 +508,12 @@ static inheritance_status zend_do_perform_arg_type_hint_check( /* Contravariant type check is performed as a covariant type check with swapped * argument order. */ return zend_perform_covariant_type_check( - unresolved_class, proto, proto_arg_info, fe, fe_arg_info); + proto->common.scope, proto_arg_info->type, fe->common.scope, fe_arg_info->type); } /* }}} */ static inheritance_status zend_do_perform_implementation_check( - zend_string **unresolved_class, const zend_function *fe, const zend_function *proto) /* {{{ */ + const zend_function *fe, const zend_function *proto) /* {{{ */ { uint32_t i, num_args; inheritance_status status, local_status; @@ -478,8 +579,7 @@ static inheritance_status zend_do_perform_implementation_check( proto_arg_info = &proto->common.arg_info[proto->common.num_args]; } - local_status = zend_do_perform_arg_type_hint_check( - unresolved_class, fe, fe_arg_info, proto, proto_arg_info); + local_status = zend_do_perform_arg_type_hint_check(fe, fe_arg_info, proto, proto_arg_info); if (UNEXPECTED(local_status != INHERITANCE_SUCCESS)) { if (UNEXPECTED(local_status == INHERITANCE_ERROR)) { @@ -490,7 +590,7 @@ static inheritance_status zend_do_perform_implementation_check( } /* by-ref constraints on arguments are invariant */ - if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) { + if (ZEND_ARG_SEND_MODE(fe_arg_info) != ZEND_ARG_SEND_MODE(proto_arg_info)) { return INHERITANCE_ERROR; } } @@ -504,7 +604,8 @@ static inheritance_status zend_do_perform_implementation_check( } local_status = zend_perform_covariant_type_check( - unresolved_class, fe, fe->common.arg_info - 1, proto, proto->common.arg_info - 1); + fe->common.scope, fe->common.arg_info[-1].type, + proto->common.scope, proto->common.arg_info[-1].type); if (UNEXPECTED(local_status != INHERITANCE_SUCCESS)) { if (UNEXPECTED(local_status == INHERITANCE_ERROR)) { @@ -521,33 +622,10 @@ static inheritance_status zend_do_perform_implementation_check( static ZEND_COLD void zend_append_type_hint(smart_str *str, const zend_function *fptr, zend_arg_info *arg_info, int return_hint) /* {{{ */ { - - if (ZEND_TYPE_IS_SET(arg_info->type) && ZEND_TYPE_ALLOW_NULL(arg_info->type)) { - smart_str_appendc(str, '?'); - } - - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - const char *class_name; - size_t class_name_len; - - class_name = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)); - class_name_len = ZSTR_LEN(ZEND_TYPE_NAME(arg_info->type)); - - if (!strcasecmp(class_name, "self") && fptr->common.scope) { - class_name = ZSTR_VAL(fptr->common.scope->name); - class_name_len = ZSTR_LEN(fptr->common.scope->name); - } else if (!strcasecmp(class_name, "parent") && fptr->common.scope && fptr->common.scope->parent) { - class_name = ZSTR_VAL(fptr->common.scope->parent->name); - class_name_len = ZSTR_LEN(fptr->common.scope->parent->name); - } - - smart_str_appendl(str, class_name, class_name_len); - if (!return_hint) { - smart_str_appendc(str, ' '); - } - } else if (ZEND_TYPE_IS_CODE(arg_info->type)) { - const char *type_name = zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)); - smart_str_appends(str, type_name); + if (ZEND_TYPE_IS_SET(arg_info->type)) { + zend_string *type_str = zend_type_to_string_resolved(arg_info->type, fptr->common.scope); + smart_str_append(str, type_str); + zend_string_release(type_str); if (!return_hint) { smart_str_appendc(str, ' '); } @@ -584,11 +662,11 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function for (i = 0; i < num_args;) { zend_append_type_hint(&str, fptr, arg_info, 0); - if (arg_info->pass_by_reference) { + if (ZEND_ARG_SEND_MODE(arg_info)) { smart_str_appendc(&str, '&'); } - if (arg_info->is_variadic) { + if (ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(&str, "..."); } @@ -605,7 +683,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function smart_str_append_unsigned(&str, i); } - if (i >= required && !arg_info->is_variadic) { + if (i >= required && !ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(&str, " = "); if (fptr->type == ZEND_USER_FUNCTION) { zend_op *precv = NULL; @@ -685,66 +763,41 @@ static zend_always_inline uint32_t func_lineno(const zend_function *fn) { } static void ZEND_COLD emit_incompatible_method_error( - int error_level, const char *error_verb, const zend_function *child, const zend_function *parent, - inheritance_status status, zend_string *unresolved_class) { + inheritance_status status) { zend_string *parent_prototype = zend_get_function_declaration(parent); zend_string *child_prototype = zend_get_function_declaration(child); if (status == INHERITANCE_UNRESOLVED) { - zend_error_at(error_level, NULL, func_lineno(child), + /* Fetch the first unresolved class from registered autoloads */ + zend_string *unresolved_class = NULL; + ZEND_HASH_FOREACH_STR_KEY(CG(delayed_autoloads), unresolved_class) { + break; + } ZEND_HASH_FOREACH_END(); + ZEND_ASSERT(unresolved_class); + + zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child), "Could not check compatibility between %s and %s, because class %s is not available", ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype), ZSTR_VAL(unresolved_class)); } else { - zend_error_at(error_level, NULL, func_lineno(child), - "Declaration of %s %s be compatible with %s", - ZSTR_VAL(child_prototype), error_verb, ZSTR_VAL(parent_prototype)); + zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child), + "Declaration of %s must be compatible with %s", + ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype)); } zend_string_efree(child_prototype); zend_string_efree(parent_prototype); } -static void ZEND_COLD emit_incompatible_method_error_or_warning( - const zend_function *child, const zend_function *parent, - inheritance_status status, zend_string *unresolved_class, zend_bool always_error) { - int error_level; - const char *error_verb; - if (always_error || - (child->common.prototype && - (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) || - ((parent->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) && - (!(child->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_perform_covariant_type_check(&unresolved_class, child, child->common.arg_info - 1, parent, parent->common.arg_info - 1) != INHERITANCE_SUCCESS)) - ) { - error_level = E_COMPILE_ERROR; - error_verb = "must"; - } else { - error_level = E_WARNING; - error_verb = "should"; - } - emit_incompatible_method_error( - error_level, error_verb, child, parent, status, unresolved_class); -} - static void perform_delayable_implementation_check( zend_class_entry *ce, const zend_function *fe, - const zend_function *proto, zend_bool always_error) + const zend_function *proto) { - zend_string *unresolved_class; - inheritance_status status = zend_do_perform_implementation_check( - &unresolved_class, fe, proto); - + inheritance_status status = zend_do_perform_implementation_check(fe, proto); if (UNEXPECTED(status != INHERITANCE_SUCCESS)) { if (EXPECTED(status == INHERITANCE_UNRESOLVED)) { - add_compatibility_obligation(ce, fe, proto, always_error); + add_compatibility_obligation(ce, fe, proto); } else { ZEND_ASSERT(status == INHERITANCE_ERROR); - if (always_error) { - emit_incompatible_method_error( - E_COMPILE_ERROR, "must", fe, proto, status, unresolved_class); - } else { - emit_incompatible_method_error_or_warning( - fe, proto, status, unresolved_class, always_error); - } + emit_incompatible_method_error(fe, proto, status); } } } @@ -843,13 +896,9 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(z if (!checked) { if (check_only) { - zend_string *unresolved_class; - - return zend_do_perform_implementation_check( - &unresolved_class, child, parent); + return zend_do_perform_implementation_check(child, parent); } - perform_delayable_implementation_check( - ce, child, parent, /*always_error*/0); + perform_delayable_implementation_check(ce, child, parent); } return INHERITANCE_SUCCESS; } @@ -897,50 +946,38 @@ static zend_always_inline void do_inherit_method(zend_string *key, zend_function inheritance_status property_types_compatible( const zend_property_info *parent_info, const zend_property_info *child_info) { - zend_string *parent_name, *child_name; - zend_class_entry *parent_type_ce, *child_type_ce; - if (parent_info->type == child_info->type) { + if (ZEND_TYPE_PURE_MASK(parent_info->type) == ZEND_TYPE_PURE_MASK(child_info->type) + && ZEND_TYPE_NAME(parent_info->type) == ZEND_TYPE_NAME(child_info->type)) { return INHERITANCE_SUCCESS; } - if (!ZEND_TYPE_IS_CLASS(parent_info->type) || !ZEND_TYPE_IS_CLASS(child_info->type) || - ZEND_TYPE_ALLOW_NULL(parent_info->type) != ZEND_TYPE_ALLOW_NULL(child_info->type)) { + if (ZEND_TYPE_IS_SET(parent_info->type) != ZEND_TYPE_IS_SET(child_info->type)) { return INHERITANCE_ERROR; } - parent_name = ZEND_TYPE_IS_CE(parent_info->type) - ? ZEND_TYPE_CE(parent_info->type)->name - : resolve_class_name(parent_info->ce, ZEND_TYPE_NAME(parent_info->type)); - child_name = ZEND_TYPE_IS_CE(child_info->type) - ? ZEND_TYPE_CE(child_info->type)->name - : resolve_class_name(child_info->ce, ZEND_TYPE_NAME(child_info->type)); - if (zend_string_equals_ci(parent_name, child_name)) { + /* Perform a covariant type check in both directions to determined invariance. */ + inheritance_status status1 = zend_perform_covariant_type_check( + child_info->ce, child_info->type, parent_info->ce, parent_info->type); + inheritance_status status2 = zend_perform_covariant_type_check( + parent_info->ce, parent_info->type, child_info->ce, child_info->type); + if (status1 == INHERITANCE_SUCCESS && status2 == INHERITANCE_SUCCESS) { return INHERITANCE_SUCCESS; } - - /* Check for class aliases */ - parent_type_ce = ZEND_TYPE_IS_CE(parent_info->type) - ? ZEND_TYPE_CE(parent_info->type) - : lookup_class(parent_info->ce, parent_name); - child_type_ce = ZEND_TYPE_IS_CE(child_info->type) - ? ZEND_TYPE_CE(child_info->type) - : lookup_class(child_info->ce, child_name); - if (!parent_type_ce || !child_type_ce) { - return INHERITANCE_UNRESOLVED; + if (status1 == INHERITANCE_ERROR || status2 == INHERITANCE_ERROR) { + return INHERITANCE_ERROR; } - return parent_type_ce == child_type_ce ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; + ZEND_ASSERT(status1 == INHERITANCE_UNRESOLVED || status2 == INHERITANCE_UNRESOLVED); + return INHERITANCE_UNRESOLVED; } static void emit_incompatible_property_error( const zend_property_info *child, const zend_property_info *parent) { + zend_string *type_str = zend_type_to_string_resolved(parent->type, parent->ce); zend_error_noreturn(E_COMPILE_ERROR, - "Type of %s::$%s must be %s%s (as in class %s)", + "Type of %s::$%s must be %s (as in class %s)", ZSTR_VAL(child->ce->name), zend_get_unmangled_property_name(child->name), - ZEND_TYPE_ALLOW_NULL(parent->type) ? "?" : "", - ZEND_TYPE_IS_CLASS(parent->type) - ? ZSTR_VAL(ZEND_TYPE_IS_CE(parent->type) ? ZEND_TYPE_CE(parent->type)->name : resolve_class_name(parent->ce, ZEND_TYPE_NAME(parent->type))) - : zend_get_type_by_const(ZEND_TYPE_CODE(parent->type)), + ZSTR_VAL(type_str), ZSTR_VAL(parent->ce->name)); } @@ -1502,14 +1539,11 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen ce->serialize_func = fe; } else if (zend_string_equals_literal(mname, "unserialize")) { ce->unserialize_func = fe; - } else if (ZSTR_LEN(ce->name) != ZSTR_LEN(mname) && (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_')) { + } else if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') { /* pass */ } else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) { ce->clone = fe; } else if (zend_string_equals_literal(mname, ZEND_CONSTRUCTOR_FUNC_NAME)) { - if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) { - zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name)); - } ce->constructor = fe; } else if (zend_string_equals_literal(mname, ZEND_DESTRUCTOR_FUNC_NAME)) { ce->destructor = fe; @@ -1533,17 +1567,6 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen ce->__tostring = fe; } else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) { ce->__debugInfo = fe; - } else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) { - zend_string *lowercase_name = zend_string_tolower(ce->name); - lowercase_name = zend_new_interned_string(lowercase_name); - if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) { - if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) { - zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name)); - } - ce->constructor = fe; - fe->common.fn_flags |= ZEND_ACC_CTOR; - } - zend_string_release_ex(lowercase_name, 0); } } /* }}} */ @@ -1569,13 +1592,11 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s if ((existing_fn = zend_hash_find_ptr(*overridden, key)) != NULL) { if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) { /* Make sure the trait method is compatible with previosly declared abstract method */ - perform_delayable_implementation_check( - ce, fn, existing_fn, /*always_error*/ 1); + perform_delayable_implementation_check(ce, fn, existing_fn); } if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { /* Make sure the abstract declaration is compatible with previous declaration */ - perform_delayable_implementation_check( - ce, existing_fn, fn, /*always_error*/ 1); + perform_delayable_implementation_check(ce, existing_fn, fn); return; } } @@ -1588,12 +1609,10 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT && (existing_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) { /* Make sure the trait method is compatible with previosly declared abstract method */ - perform_delayable_implementation_check( - ce, fn, existing_fn, /*always_error*/ 1); + perform_delayable_implementation_check(ce, fn, existing_fn); } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { /* Make sure the abstract declaration is compatible with previous declaration */ - perform_delayable_implementation_check( - ce, existing_fn, fn, /*always_error*/ 1); + perform_delayable_implementation_check(ce, existing_fn, fn); return; } else if (UNEXPECTED(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) { /* two traits can't define the same non-abstract method */ @@ -2029,9 +2048,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent Z_TRY_ADDREF_P(prop_value); doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL; - if (ZEND_TYPE_IS_NAME(property_info->type)) { - zend_string_addref(ZEND_TYPE_NAME(property_info->type)); - } + zend_type_copy_ctor(&property_info->type, /* persistent */ 0); zend_declare_typed_property(ce, prop_name, prop_value, flags, doc_comment, property_info->type); zend_string_release_ex(prop_name, 0); } ZEND_HASH_FOREACH_END(); @@ -2141,32 +2158,6 @@ static void zend_do_bind_traits(zend_class_entry *ce) /* {{{ */ zend_do_traits_property_binding(ce, traits); efree(traits); - - /* Emit E_DEPRECATED for PHP 4 constructors */ - zend_check_deprecated_constructor(ce); -} -/* }}} */ - - -static zend_bool zend_has_deprecated_constructor(const zend_class_entry *ce) /* {{{ */ -{ - const zend_string *constructor_name; - if (!ce->constructor) { - return 0; - } - constructor_name = ce->constructor->common.function_name; - return !zend_binary_strcasecmp( - ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), - ZSTR_VAL(constructor_name), ZSTR_LEN(constructor_name) - ); -} -/* }}} */ - -void zend_check_deprecated_constructor(const zend_class_entry *ce) /* {{{ */ -{ - if (zend_has_deprecated_constructor(ce)) { - zend_error(E_DEPRECATED, "Methods with the same name as their class will not be constructors in a future version of PHP; %s has a deprecated constructor", ZSTR_VAL(ce->name)); - } } /* }}} */ @@ -2242,7 +2233,6 @@ typedef struct { struct { const zend_function *parent_fn; const zend_function *child_fn; - zend_bool always_error; }; struct { const zend_property_info *parent_prop; @@ -2290,14 +2280,12 @@ static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *de } static void add_compatibility_obligation( - zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn, - zend_bool always_error) { + zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn) { HashTable *obligations = get_or_init_obligations_for_class(ce); variance_obligation *obligation = emalloc(sizeof(variance_obligation)); obligation->type = OBLIGATION_COMPATIBILITY; obligation->child_fn = child_fn; obligation->parent_fn = parent_fn; - obligation->always_error = always_error; zend_hash_next_index_insert_ptr(obligations, obligation); } @@ -2325,18 +2313,14 @@ static int check_variance_obligation(zval *zv) { return ZEND_HASH_APPLY_KEEP; } } else if (obligation->type == OBLIGATION_COMPATIBILITY) { - zend_string *unresolved_class; inheritance_status status = zend_do_perform_implementation_check( - &unresolved_class, obligation->child_fn, obligation->parent_fn); - + obligation->child_fn, obligation->parent_fn); if (UNEXPECTED(status != INHERITANCE_SUCCESS)) { if (EXPECTED(status == INHERITANCE_UNRESOLVED)) { return ZEND_HASH_APPLY_KEEP; } ZEND_ASSERT(status == INHERITANCE_ERROR); - emit_incompatible_method_error_or_warning( - obligation->child_fn, obligation->parent_fn, status, unresolved_class, - obligation->always_error); + emit_incompatible_method_error(obligation->child_fn, obligation->parent_fn, status); } /* Either the compatibility check was successful or only threw a warning. */ } else { @@ -2399,17 +2383,14 @@ static void report_variance_errors(zend_class_entry *ce) { ZEND_ASSERT(obligations != NULL); ZEND_HASH_FOREACH_PTR(obligations, obligation) { - inheritance_status status; - zend_string *unresolved_class; - if (obligation->type == OBLIGATION_COMPATIBILITY) { - /* Just used to fetch the unresolved_class in this case. */ - status = zend_do_perform_implementation_check( - &unresolved_class, obligation->child_fn, obligation->parent_fn); + /* Just used to populate the delayed_autoloads table, + * which will be used when printing the "unresolved" error. */ + inheritance_status status = zend_do_perform_implementation_check( + obligation->child_fn, obligation->parent_fn); ZEND_ASSERT(status == INHERITANCE_UNRESOLVED); - emit_incompatible_method_error_or_warning( - obligation->child_fn, obligation->parent_fn, - status, unresolved_class, obligation->always_error); + emit_incompatible_method_error( + obligation->child_fn, obligation->parent_fn, status); } else if (obligation->type == OBLIGATION_PROPERTY_COMPATIBILITY) { emit_incompatible_property_error(obligation->child_prop, obligation->parent_prop); } else { @@ -2522,7 +2503,6 @@ ZEND_API int zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_nam /* Check whether early binding is prevented due to unresolved types in inheritance checks. */ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */ { - inheritance_status ret = INHERITANCE_SUCCESS; zend_string *key; zend_function *parent_func; zend_property_info *parent_info; @@ -2535,11 +2515,7 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e do_inheritance_check_on_method_ex(child_func, parent_func, ce, NULL, 1, 0); if (UNEXPECTED(status != INHERITANCE_SUCCESS)) { - if (EXPECTED(status == INHERITANCE_UNRESOLVED)) { - return INHERITANCE_UNRESOLVED; - } - ZEND_ASSERT(status == INHERITANCE_ERROR); - ret = INHERITANCE_ERROR; + return status; } } } ZEND_HASH_FOREACH_END(); @@ -2556,17 +2532,13 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e if (ZEND_TYPE_IS_SET(child_info->type)) { inheritance_status status = property_types_compatible(parent_info, child_info); if (UNEXPECTED(status != INHERITANCE_SUCCESS)) { - if (EXPECTED(status == INHERITANCE_UNRESOLVED)) { - return INHERITANCE_UNRESOLVED; - } - ZEND_ASSERT(status == INHERITANCE_ERROR); - ret = INHERITANCE_ERROR; + return status; } } } } ZEND_HASH_FOREACH_END(); - return ret; + return INHERITANCE_SUCCESS; } /* }}} */ diff --git a/Zend/zend_inheritance.h b/Zend/zend_inheritance.h index c4e9e10675..6cf2d1b78d 100644 --- a/Zend/zend_inheritance.h +++ b/Zend/zend_inheritance.h @@ -33,7 +33,6 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par ZEND_API int zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name); void zend_verify_abstract_class(zend_class_entry *ce); -void zend_check_deprecated_constructor(const zend_class_entry *ce); void zend_build_properties_info_table(zend_class_entry *ce); zend_bool zend_try_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce, zend_string *lcname, zval *delayed_early_binding); diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index ff6784be31..d2b96e6bf3 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -20,6 +20,7 @@ #include "zend_API.h" #include "zend_interfaces.h" #include "zend_exceptions.h" +#include "zend_interfaces_arginfo.h" ZEND_API zend_class_entry *zend_ce_traversable; ZEND_API zend_class_entry *zend_ce_aggregate; @@ -30,7 +31,7 @@ ZEND_API zend_class_entry *zend_ce_countable; /* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ -ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2) +ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2) { int result; zend_fcall_info fci; @@ -45,7 +46,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun } fci.size = sizeof(fci); - fci.object = object ? Z_OBJ_P(object) : NULL; + fci.object = object; fci.retval = retval_ptr ? retval_ptr : &retval; fci.param_count = param_count; fci.params = params; @@ -62,7 +63,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun ZVAL_UNDEF(&fci.function_name); /* Unused */ if (!obj_ce) { - obj_ce = object ? Z_OBJCE_P(object) : NULL; + obj_ce = object ? object->ce : NULL; } if (!fn_proxy || !*fn_proxy) { if (EXPECTED(obj_ce)) { @@ -87,7 +88,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun } if (object) { - fcic.called_scope = Z_OBJCE_P(object); + fcic.called_scope = object->ce; } else { zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); @@ -99,13 +100,13 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun fcic.called_scope = called_scope; } } - fcic.object = object ? Z_OBJ_P(object) : NULL; + fcic.object = object; result = zend_call_function(&fci, &fcic); } if (result == FAILURE) { /* error at c-level */ if (!obj_ce) { - obj_ce = object ? Z_OBJCE_P(object) : NULL; + obj_ce = object ? object->ce : NULL; } if (!EG(exception)) { zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", function_name); @@ -124,7 +125,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun /* {{{ zend_user_it_new_iterator */ ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *retval) { - zend_call_method_with_0_params(object, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", retval); + zend_call_method_with_0_params(Z_OBJ_P(object), ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", retval); } /* }}} */ @@ -160,7 +161,7 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter) zval more; int result; - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more); result = i_zend_is_true(&more); zval_ptr_dtor(&more); return result ? SUCCESS : FAILURE; @@ -176,7 +177,7 @@ ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter) zval *object = &iter->it.data; if (Z_ISUNDEF(iter->value)) { - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_current, "current", &iter->value); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_current, "current", &iter->value); } return &iter->value; } @@ -189,7 +190,7 @@ ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *ke zval *object = &iter->it.data; zval retval; - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_key, "key", &retval); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_key, "key", &retval); if (Z_TYPE(retval) != IS_UNDEF) { ZVAL_ZVAL(key, &retval, 1, 1); @@ -210,7 +211,7 @@ ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter) zval *object = &iter->it.data; zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL); } /* }}} */ @@ -221,7 +222,7 @@ ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter) zval *object = &iter->it.data; zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL); } /* }}} */ @@ -438,7 +439,7 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *b zval retval; int result; - zend_call_method_with_0_params(object, ce, &ce->serialize_func, "serialize", &retval); + zend_call_method_with_0_params(Z_OBJ_P(object), ce, &ce->serialize_func, "serialize", &retval); if (Z_TYPE(retval) == IS_UNDEF || EG(exception)) { @@ -479,7 +480,7 @@ ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const uns ZVAL_STRINGL(&zdata, (char*)buf, buf_len); - zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, &zdata); + zend_call_method_with_1_params(Z_OBJ_P(object), ce, &ce->unserialize_func, "unserialize", NULL, &zdata); zval_ptr_dtor(&zdata); @@ -511,7 +512,7 @@ static int zend_implement_serializable(zend_class_entry *interface, zend_class_e { if (class_type->parent && (class_type->parent->serialize || class_type->parent->unserialize) - && !instanceof_function_ex(class_type->parent, zend_ce_serializable, 1)) { + && !zend_class_implements_interface(class_type->parent, zend_ce_serializable)) { return FAILURE; } if (!class_type->serialize) { @@ -533,57 +534,37 @@ static int zend_implement_countable(zend_class_entry *interface, zend_class_entr /* {{{ function tables */ static const zend_function_entry zend_funcs_aggregate[] = { - ZEND_ABSTRACT_ME(iterator, getIterator, NULL) + ZEND_ABSTRACT_ME(iterator, getIterator, arginfo_class_IteratorAggregate_getIterator) ZEND_FE_END }; static const zend_function_entry zend_funcs_iterator[] = { - ZEND_ABSTRACT_ME(iterator, current, NULL) - ZEND_ABSTRACT_ME(iterator, next, NULL) - ZEND_ABSTRACT_ME(iterator, key, NULL) - ZEND_ABSTRACT_ME(iterator, valid, NULL) - ZEND_ABSTRACT_ME(iterator, rewind, NULL) + ZEND_ABSTRACT_ME(iterator, current, arginfo_class_Iterator_current) + ZEND_ABSTRACT_ME(iterator, next, arginfo_class_Iterator_next) + ZEND_ABSTRACT_ME(iterator, key, arginfo_class_Iterator_key) + ZEND_ABSTRACT_ME(iterator, valid, arginfo_class_Iterator_valid) + ZEND_ABSTRACT_ME(iterator, rewind, arginfo_class_Iterator_rewind) ZEND_FE_END }; static const zend_function_entry *zend_funcs_traversable = NULL; -ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset, 0, 0, 1) - ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /* actually this should be return by ref but atm cannot be */ - ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_value, 0, 0, 2) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - static const zend_function_entry zend_funcs_arrayaccess[] = { - ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset) - ZEND_ABSTRACT_ME(arrayaccess, offsetGet, arginfo_arrayaccess_offset_get) - ZEND_ABSTRACT_ME(arrayaccess, offsetSet, arginfo_arrayaccess_offset_value) - ZEND_ABSTRACT_ME(arrayaccess, offsetUnset, arginfo_arrayaccess_offset) + ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_class_ArrayAccess_offsetExists) + ZEND_ABSTRACT_ME(arrayaccess, offsetGet, arginfo_class_ArrayAccess_offsetGet) + ZEND_ABSTRACT_ME(arrayaccess, offsetSet, arginfo_class_ArrayAccess_offsetSet) + ZEND_ABSTRACT_ME(arrayaccess, offsetUnset, arginfo_class_ArrayAccess_offsetUnset) ZEND_FE_END }; -ZEND_BEGIN_ARG_INFO(arginfo_serializable_serialize, 0) - ZEND_ARG_INFO(0, serialized) -ZEND_END_ARG_INFO() - static const zend_function_entry zend_funcs_serializable[] = { - ZEND_ABSTRACT_ME(serializable, serialize, NULL) - ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) + ZEND_ABSTRACT_ME(serializable, serialize, arginfo_class_Serializable_serialize) + ZEND_FENTRY(unserialize, NULL, arginfo_class_Serializable_unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) ZEND_FE_END }; -ZEND_BEGIN_ARG_INFO(arginfo_countable_count, 0) -ZEND_END_ARG_INFO() - static const zend_function_entry zend_funcs_countable[] = { - ZEND_ABSTRACT_ME(Countable, count, arginfo_countable_count) + ZEND_ABSTRACT_ME(Countable, count, arginfo_class_Countable_count) ZEND_FE_END }; /* }}} */ diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h index 44770a1813..e7d0315ac5 100644 --- a/Zend/zend_interfaces.h +++ b/Zend/zend_interfaces.h @@ -37,7 +37,7 @@ typedef struct _zend_user_iterator { zval value; } zend_user_iterator; -ZEND_API zval* zend_call_method(zval *object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2); +ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2); #define zend_call_method_with_0_params(obj, obj_ce, fn_proxy, function_name, retval) \ zend_call_method(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, 0, NULL, NULL) diff --git a/Zend/zend_interfaces.stub.php b/Zend/zend_interfaces.stub.php new file mode 100644 index 0000000000..882a21e600 --- /dev/null +++ b/Zend/zend_interfaces.stub.php @@ -0,0 +1,51 @@ +<?php + +interface Traversable {} + +interface IteratorAggregate extends Traversable +{ + /** @return Traversable */ + function getIterator(); +} + +interface Iterator extends Traversable +{ + function current(); + + /** @return void */ + function next(); + + function key(); + + /** @return bool */ + function valid(); + + /** @return void */ + function rewind(); +} + +interface ArrayAccess +{ + function offsetExists($offset); + + /* actually this should be return by ref but atm cannot be */ + function offsetGet($offset); + + function offsetSet($offset, $value); + + function offsetUnset($offset); +} + +interface Serializable +{ + /** @return string */ + function serialize(); + + function unserialize(string $serialized); +} + +interface Countable +{ + /** @return int */ + function count(); +} diff --git a/Zend/zend_interfaces_arginfo.h b/Zend/zend_interfaces_arginfo.h new file mode 100644 index 0000000000..fee57057af --- /dev/null +++ b/Zend/zend_interfaces_arginfo.h @@ -0,0 +1,35 @@ +/* This is a generated file, edit the .stub.php file instead. */ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IteratorAggregate_getIterator, 0, 0, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Iterator_current arginfo_class_IteratorAggregate_getIterator + +#define arginfo_class_Iterator_next arginfo_class_IteratorAggregate_getIterator + +#define arginfo_class_Iterator_key arginfo_class_IteratorAggregate_getIterator + +#define arginfo_class_Iterator_valid arginfo_class_IteratorAggregate_getIterator + +#define arginfo_class_Iterator_rewind arginfo_class_IteratorAggregate_getIterator + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ArrayAccess_offsetExists, 0, 0, 1) + ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +#define arginfo_class_ArrayAccess_offsetGet arginfo_class_ArrayAccess_offsetExists + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ArrayAccess_offsetSet, 0, 0, 2) + ZEND_ARG_INFO(0, offset) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +#define arginfo_class_ArrayAccess_offsetUnset arginfo_class_ArrayAccess_offsetExists + +#define arginfo_class_Serializable_serialize arginfo_class_IteratorAggregate_getIterator + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Serializable_unserialize, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, serialized, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Countable_count arginfo_class_IteratorAggregate_getIterator diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index 379a316c38..c0bb418f3a 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -24,7 +24,7 @@ static zend_class_entry zend_iterator_class_entry; static void iter_wrapper_free(zend_object *object); static void iter_wrapper_dtor(zend_object *object); -static HashTable *iter_wrapper_get_gc(zval *object, zval **table, int *n); +static HashTable *iter_wrapper_get_gc(zend_object *object, zval **table, int *n); static const zend_object_handlers iterator_object_handlers = { 0, @@ -36,18 +36,14 @@ static const zend_object_handlers iterator_object_handlers = { NULL, /* read dim */ NULL, /* write dim */ NULL, - NULL, /* get */ - NULL, /* set */ NULL, /* has prop */ NULL, /* unset prop */ NULL, /* has dim */ NULL, /* unset dim */ NULL, /* props get */ NULL, /* method get */ - NULL, /* call */ NULL, /* get ctor */ NULL, /* get class name */ - NULL, /* compare */ NULL, /* cast */ NULL, /* count */ NULL, /* get_debug_info */ @@ -72,7 +68,7 @@ static void iter_wrapper_dtor(zend_object *object) { } -static HashTable *iter_wrapper_get_gc(zval *object, zval **table, int *n) { +static HashTable *iter_wrapper_get_gc(zend_object *object, zval **table, int *n) { /* TODO: We need a get_gc iterator handler */ *table = NULL; *n = 0; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index f3bb663e0c..57e88e630d 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -70,8 +70,9 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %left '&' %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL +%left '.' %left T_SL T_SR -%left '+' '-' '.' +%left '+' '-' %left '*' '/' '%' %precedence '!' %precedence T_INSTANCEOF @@ -254,7 +255,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type <ast> array_pair non_empty_array_pair_list array_pair_list possible_array_pair %type <ast> isset_variable type return_type type_expr %type <ast> identifier -%type <ast> inline_function +%type <ast> inline_function union_type %type <num> returns_ref function fn is_reference is_variadic variable_modifiers %type <num> method_modifiers non_empty_member_modifiers member_modifier @@ -659,6 +660,7 @@ optional_type: type_expr: type { $$ = $1; } | '?' type { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; } + | union_type { $$ = $1; } ; type: @@ -667,6 +669,11 @@ type: | name { $$ = $1; } ; +union_type: + type '|' type { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } + | union_type '|' type { $$ = zend_ast_list_add($1, $3); } +; + return_type: /* empty */ { $$ = NULL; } | ':' type_expr { $$ = $2; } @@ -965,7 +972,6 @@ expr: | '(' expr ')' { $$ = $2; if ($$->kind == ZEND_AST_CONDITIONAL) $$->attr = ZEND_PARENTHESIZED_CONDITIONAL; - if ($$->kind == ZEND_AST_BINARY_OP && $$->attr == ZEND_CONCAT) $$->attr = ZEND_PARENTHESIZED_CONCAT; } | new_expr { $$ = $1; } | expr '?' expr ':' expr diff --git a/Zend/zend_language_scanner.h b/Zend/zend_language_scanner.h index 3640b9a5ea..4d51a064fc 100644 --- a/Zend/zend_language_scanner.h +++ b/Zend/zend_language_scanner.h @@ -66,7 +66,7 @@ typedef struct _zend_heredoc_label { BEGIN_EXTERN_C() ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state); ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state); -ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename); +ZEND_API int zend_prepare_string_for_scanning(zval *str, const char *filename); ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding); ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding); ZEND_API void zend_lex_tstring(zval *zv); diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 7dcb4dfcee..4b9e89ae67 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -685,7 +685,7 @@ zend_op_array *compile_filename(int type, zval *filename) return retval; } -ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename) +ZEND_API int zend_prepare_string_for_scanning(zval *str, const char *filename) { char *buf; size_t size, old_len; @@ -753,7 +753,7 @@ ZEND_API size_t zend_get_scanned_file_offset(void) return offset; } -zend_op_array *compile_string(zval *source_string, char *filename) +zend_op_array *compile_string(zval *source_string, const char *filename) { zend_lex_state original_lex_state; zend_op_array *op_array = NULL; @@ -784,7 +784,7 @@ zend_op_array *compile_string(zval *source_string, char *filename) BEGIN_EXTERN_C() -int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini) +int highlight_file(const char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini) { zend_lex_state original_lex_state; zend_file_handle file_handle; @@ -806,7 +806,7 @@ int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlight return SUCCESS; } -int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name) +int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, const char *str_name) { zend_lex_state original_lex_state; zval tmp; @@ -2190,8 +2190,11 @@ inline_char_handler: if (YYCURSOR < YYLIMIT) { YYCURSOR++; - } else if (!SCNG(heredoc_scan_ahead)) { - zend_error(E_COMPILE_WARNING, "Unterminated comment starting line %d", CG(zend_lineno)); + } else { + zend_throw_exception_ex(zend_ce_parse_error, 0, "Unterminated comment starting line %d", CG(zend_lineno)); + if (PARSER_MODE()) { + RETURN_TOKEN(T_ERROR); + } } yyleng = YYCURSOR - SCNG(yy_text); @@ -2859,14 +2862,7 @@ nowdoc_scan_done: RETURN_TOKEN(END); } - if (!SCNG(heredoc_scan_ahead)) { - zend_error(E_COMPILE_WARNING, "Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); - } - if (PARSER_MODE()) { - goto restart; - } else { - RETURN_TOKEN(T_BAD_CHARACTER); - } + RETURN_TOKEN(T_BAD_CHARACTER); } */ diff --git a/Zend/zend_list.c b/Zend/zend_list.c index 21d013a589..2288cf6913 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -113,7 +113,7 @@ ZEND_API void *zend_fetch_resource2(zend_resource *res, const char *resource_typ if (resource_type_name) { const char *space; const char *class_name = get_active_class_name(&space); - zend_error(E_WARNING, "%s%s%s(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); + zend_type_error("%s%s%s(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); } return NULL; @@ -128,7 +128,7 @@ ZEND_API void *zend_fetch_resource(zend_resource *res, const char *resource_type if (resource_type_name) { const char *space; const char *class_name = get_active_class_name(&space); - zend_error(E_WARNING, "%s%s%s(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); + zend_type_error("%s%s%s(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); } return NULL; @@ -140,14 +140,14 @@ ZEND_API void *zend_fetch_resource_ex(zval *res, const char *resource_type_name, if (res == NULL) { if (resource_type_name) { class_name = get_active_class_name(&space); - zend_error(E_WARNING, "%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(), resource_type_name); + zend_type_error("%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(), resource_type_name); } return NULL; } if (Z_TYPE_P(res) != IS_RESOURCE) { if (resource_type_name) { class_name = get_active_class_name(&space); - zend_error(E_WARNING, "%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); + zend_type_error("%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); } return NULL; } @@ -161,14 +161,14 @@ ZEND_API void *zend_fetch_resource2_ex(zval *res, const char *resource_type_name if (res == NULL) { if (resource_type_name) { class_name = get_active_class_name(&space); - zend_error(E_WARNING, "%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(), resource_type_name); + zend_type_error("%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(), resource_type_name); } return NULL; } if (Z_TYPE_P(res) != IS_RESOURCE) { if (resource_type_name) { class_name = get_active_class_name(&space); - zend_error(E_WARNING, "%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); + zend_type_error("%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(), resource_type_name); } return NULL; } @@ -209,6 +209,7 @@ void plist_entry_destructor(zval *zv) ZEND_API int zend_init_rsrc_list(void) { zend_hash_init(&EG(regular_list), 8, NULL, list_entry_destructor, 0); + EG(regular_list).nNextFreeElement = 0; return SUCCESS; } diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index 908acd7d32..047d9d77ce 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -31,7 +31,7 @@ #define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module #define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module -#define ZEND_MODULE_API_NO 20190902 +#define ZEND_MODULE_API_NO 20190128 #ifdef ZTS #define USING_ZTS 1 #else diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 610b15c6aa..668a1ef9d3 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -104,10 +104,8 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */ +ZEND_API HashTable *zend_std_get_properties(zend_object *zobj) /* {{{ */ { - zend_object *zobj; - zobj = Z_OBJ_P(object); if (!zobj->properties) { rebuild_object_properties(zobj); } @@ -115,15 +113,13 @@ ZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */ } /* }}} */ -ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ */ +ZEND_API HashTable *zend_std_get_gc(zend_object *zobj, zval **table, int *n) /* {{{ */ { - if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) { + if (zobj->handlers->get_properties != zend_std_get_properties) { *table = NULL; *n = 0; - return Z_OBJ_HANDLER_P(object, get_properties)(object); + return zobj->handlers->get_properties(zobj); } else { - zend_object *zobj = Z_OBJ_P(object); - if (zobj->properties) { *table = NULL; *n = 0; @@ -142,15 +138,15 @@ ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ * } /* }}} */ -ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ */ +ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); + zend_class_entry *ce = object->ce; zval retval; HashTable *ht; if (!ce->__debugInfo) { *is_temp = 0; - return Z_OBJ_HANDLER_P(object, get_properties)(object); + return object->handlers->get_properties(object); } zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval); @@ -458,7 +454,7 @@ found: } offset = property_info->offset; - if (EXPECTED(!property_info->type)) { + if (EXPECTED(!ZEND_TYPE_IS_SET(property_info->type))) { property_info = NULL; } else { *info_ptr = property_info; @@ -652,23 +648,16 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe } /* }}} */ -ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ +ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int type, void **cache_slot, zval *rv) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *retval; uintptr_t property_offset; zend_property_info *prop_info = NULL; uint32_t *guard = NULL; - - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return &EG(uninitialized_zval); - } + zend_string *tmp_name = NULL; #if DEBUG_OBJECT_HANDLERS - fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name)); + fprintf(stderr, "Read object #%d property: %s\n", zobj->handle, ZSTR_VAL(name)); #endif /* make zend_get_property_info silent if we have getter - we may want to use it */ @@ -793,7 +782,7 @@ uninit_error: ZSTR_VAL(prop_info->ce->name), ZSTR_VAL(name)); } else { - zend_error(E_NOTICE,"Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); } } retval = &EG(uninitialized_zval); @@ -805,21 +794,13 @@ exit: } /* }}} */ -ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ +ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *variable_ptr, tmp; uintptr_t property_offset; zend_property_info *prop_info = NULL; ZEND_ASSERT(!Z_ISREF_P(value)); - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return value; - } - property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__set != NULL), cache_slot, &prop_info); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) { @@ -912,7 +893,6 @@ write_std_property: } exit: - zend_tmp_string_release(tmp_name); return variable_ptr; } /* }}} */ @@ -923,12 +903,12 @@ static ZEND_COLD zend_never_inline void zend_bad_array_access(zend_class_entry * } /* }}} */ -ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */ +ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; - if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { + if (EXPECTED(zend_class_implements_interface(ce, zend_ce_arrayaccess) != 0)) { if (offset == NULL) { /* [] construct */ ZVAL_NULL(&tmp_offset); @@ -936,17 +916,16 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva ZVAL_COPY_DEREF(&tmp_offset, offset); } - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); + GC_ADDREF(object); if (type == BP_VAR_IS) { - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", rv, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetexists", rv, &tmp_offset); if (UNEXPECTED(Z_ISUNDEF_P(rv))) { - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); return NULL; } if (!i_zend_is_true(rv)) { - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); zval_ptr_dtor(rv); return &EG(uninitialized_zval); @@ -954,9 +933,9 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva zval_ptr_dtor(rv); } - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", rv, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetget", rv, &tmp_offset); - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); if (UNEXPECTED(Z_TYPE_P(rv) == IS_UNDEF)) { @@ -973,21 +952,20 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva } /* }}} */ -ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */ +ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; - if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { + if (EXPECTED(zend_class_implements_interface(ce, zend_ce_arrayaccess) != 0)) { if (!offset) { ZVAL_NULL(&tmp_offset); } else { ZVAL_COPY_DEREF(&tmp_offset, offset); } - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); - zend_call_method_with_2_params(&tmp_object, ce, NULL, "offsetset", NULL, &tmp_offset, value); - zval_ptr_dtor(&tmp_object); + GC_ADDREF(object); + zend_call_method_with_2_params(object, ce, NULL, "offsetset", NULL, &tmp_offset, value); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -995,25 +973,24 @@ ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) } /* }}} */ -ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */ +ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check_empty) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval retval, tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval retval, tmp_offset; int result; - if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { + if (EXPECTED(zend_class_implements_interface(ce, zend_ce_arrayaccess) != 0)) { ZVAL_COPY_DEREF(&tmp_offset, offset); - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", &retval, &tmp_offset); + GC_ADDREF(object); + zend_call_method_with_1_params(object, ce, NULL, "offsetexists", &retval, &tmp_offset); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); if (check_empty && result && EXPECTED(!EG(exception))) { - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", &retval, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetget", &retval, &tmp_offset); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); } - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -1023,22 +1000,14 @@ ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty) } /* }}} */ -ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *retval = NULL; uintptr_t property_offset; zend_property_info *prop_info = NULL; - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return &EG(error_zval); - } - #if DEBUG_OBJECT_HANDLERS - fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name)); + fprintf(stderr, "Ptr object #%d property: %s\n", object->handle, ZSTR_VAL(name)); #endif property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot, &prop_info); @@ -1057,7 +1026,7 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ retval = &EG(error_zval); } else { ZVAL_NULL(retval); - zend_error(E_NOTICE, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); } } } else { @@ -1074,7 +1043,6 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ zobj->properties = zend_array_dup(zobj->properties); } if (EXPECTED((retval = zend_hash_find(zobj->properties, name)) != NULL)) { - zend_tmp_string_release(tmp_name); return retval; } } @@ -1087,31 +1055,22 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ /* Notice is thrown after creation of the property, to avoid EG(std_property_info) * being overwritten in an error handler. */ if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) { - zend_error(E_NOTICE, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); } } } else if (zobj->ce->__get == NULL) { retval = &EG(error_zval); } - zend_tmp_string_release(tmp_name); return retval; } /* }}} */ -ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ +ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; uintptr_t property_offset; zend_property_info *prop_info = NULL; - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return; - } - property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__unset != NULL), cache_slot, &prop_info); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) { @@ -1129,12 +1088,12 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s if (zobj->properties) { HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND; } - goto exit; + return; } if (UNEXPECTED(Z_PROP_FLAG_P(slot) == IS_PROP_UNINIT)) { /* Reset the IS_PROP_UNINIT flag, if it exists and bypass __unset(). */ Z_PROP_FLAG_P(slot) = 0; - goto exit; + return; } } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset)) && EXPECTED(zobj->properties != NULL)) { @@ -1145,10 +1104,10 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s zobj->properties = zend_array_dup(zobj->properties); } if (EXPECTED(zend_hash_del(zobj->properties, name) != FAILURE)) { - goto exit; + return; } } else if (UNEXPECTED(EG(exception))) { - goto exit; + return; } /* magic unset */ @@ -1163,28 +1122,24 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s /* Trigger the correct error */ zend_wrong_offset(zobj->ce, name); ZEND_ASSERT(EG(exception)); - goto exit; + return; } else { /* Nothing to do: The property already does not exist. */ } } - -exit: - zend_tmp_string_release(tmp_name); } /* }}} */ -ZEND_API void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */ +ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; - if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1)) { + if (zend_class_implements_interface(ce, zend_ce_arrayaccess)) { ZVAL_COPY_DEREF(&tmp_offset, offset); - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetunset", NULL, &tmp_offset); - zval_ptr_dtor(&tmp_object); + GC_ADDREF(object); + zend_call_method_with_1_params(object, ce, NULL, "offsetunset", NULL, &tmp_offset); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -1304,6 +1259,13 @@ static ZEND_COLD zend_never_inline void zend_bad_method_call(zend_function *fbc, } /* }}} */ +static ZEND_COLD zend_never_inline void zend_abstract_method_call(zend_function *fbc) /* {{{ */ +{ + zend_throw_error(NULL, "Cannot call abstract method %s::%s()", + ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); +} +/* }}} */ + ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key) /* {{{ */ { zend_object *zobj = *obj_ptr; @@ -1364,6 +1326,10 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * } exit: + if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) { + zend_abstract_method_call(fbc); + fbc = NULL; + } if (UNEXPECTED(!key)) { ZSTR_ALLOCA_FREE(lc_method_name, use_heap); } @@ -1449,6 +1415,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st } } + if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) { + zend_abstract_method_call(fbc); + fbc = NULL; + } + if (UNEXPECTED(!key)) { zend_string_release_ex(lc_function_name, 0); } @@ -1536,7 +1507,7 @@ undeclared_property: ZVAL_DEINDIRECT(ret); if (UNEXPECTED((type == BP_VAR_R || type == BP_VAR_RW) - && Z_TYPE_P(ret) == IS_UNDEF && property_info->type != 0)) { + && Z_TYPE_P(ret) == IS_UNDEF && ZEND_TYPE_IS_SET(property_info->type))) { zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", ZSTR_VAL(property_info->ce->name), zend_get_unmangled_property_name(property_name)); @@ -1600,6 +1571,33 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ { zend_object *zobj1, *zobj2; + if (Z_TYPE_P(o1) != Z_TYPE_P(o2)) { + /* Object and non-object */ + zval casted; + if (Z_TYPE_P(o1) == IS_OBJECT) { + ZEND_ASSERT(Z_TYPE_P(o2) != IS_OBJECT); + if (Z_OBJ_HT_P(o1)->cast_object) { + if (Z_OBJ_HT_P(o1)->cast_object(Z_OBJ_P(o1), &casted, ((Z_TYPE_P(o2) == IS_FALSE || Z_TYPE_P(o2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(o2))) == FAILURE) { + return 1; + } + int ret = zend_compare(&casted, o2); + zval_ptr_dtor(&casted); + return ret; + } + } else { + ZEND_ASSERT(Z_TYPE_P(o2) == IS_OBJECT); + if (Z_OBJ_HT_P(o2)->cast_object) { + if (Z_OBJ_HT_P(o2)->cast_object(Z_OBJ_P(o2), &casted, ((Z_TYPE_P(o1) == IS_FALSE || Z_TYPE_P(o1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(o1))) == FAILURE) { + return -1; + } + int ret = zend_compare(o1, &casted); + zval_ptr_dtor(&casted); + return ret; + } + } + return 1; + } + zobj1 = Z_OBJ_P(o1); zobj2 = Z_OBJ_P(o2); @@ -1636,15 +1634,12 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ if (Z_TYPE_P(p1) != IS_UNDEF) { if (Z_TYPE_P(p2) != IS_UNDEF) { - zval result; + int ret; - if (compare_function(&result, p1, p2)==FAILURE) { - Z_UNPROTECT_RECURSION_P(o1); - return 1; - } - if (Z_LVAL(result) != 0) { + ret = zend_compare(p1, p2); + if (ret != 0) { Z_UNPROTECT_RECURSION_P(o1); - return Z_LVAL(result); + return ret; } } else { Z_UNPROTECT_RECURSION_P(o1); @@ -1672,20 +1667,13 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */ +ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has_set_exists, void **cache_slot) /* {{{ */ { - zend_object *zobj; int result; zval *value = NULL; - zend_string *name, *tmp_name; uintptr_t property_offset; zend_property_info *prop_info = NULL; - - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return 0; - } + zend_string *tmp_name = NULL; property_offset = zend_get_property_offset(zobj->ce, name, 1, cache_slot, &prop_info); @@ -1787,14 +1775,14 @@ ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type) /* {{{ */ +ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { zval retval; zend_class_entry *ce; switch (type) { case IS_STRING: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; if (ce->__tostring) { zend_call_method_with_0_params(readobj, ce, &ce->__tostring, "__tostring", &retval); if (EXPECTED(Z_TYPE(retval) == IS_STRING)) { @@ -1811,17 +1799,17 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty ZVAL_TRUE(writeobj); return SUCCESS; case IS_LONG: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to int", ZSTR_VAL(ce->name)); ZVAL_LONG(writeobj, 1); return SUCCESS; case IS_DOUBLE: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to float", ZSTR_VAL(ce->name)); ZVAL_DOUBLE(writeobj, 1); return SUCCESS; case _IS_NUMBER: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to number", ZSTR_VAL(ce->name)); ZVAL_LONG(writeobj, 1); return SUCCESS; @@ -1833,10 +1821,10 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty } /* }}} */ -ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only) /* {{{ */ { zval *func; - zend_class_entry *ce = Z_OBJCE_P(obj); + zend_class_entry *ce = obj->ce; if ((func = zend_hash_find_ex(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE), 1)) == NULL) { return FAILURE; @@ -1850,20 +1838,20 @@ ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_fun } } else { if (obj_ptr) { - *obj_ptr = Z_OBJ_P(obj); + *obj_ptr = obj; } } return SUCCESS; } /* }}} */ -ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose purpose) { +ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purpose purpose) { HashTable *ht; switch (purpose) { case ZEND_PROP_PURPOSE_DEBUG: - if (Z_OBJ_HT_P(obj)->get_debug_info) { + if (obj->handlers->get_debug_info) { int is_temp; - ht = Z_OBJ_HT_P(obj)->get_debug_info(obj, &is_temp); + ht = obj->handlers->get_debug_info(obj, &is_temp); if (ht && !is_temp && !(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_ADDREF(ht); } @@ -1874,8 +1862,7 @@ ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose pur case ZEND_PROP_PURPOSE_SERIALIZE: case ZEND_PROP_PURPOSE_VAR_EXPORT: case ZEND_PROP_PURPOSE_JSON: - case _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS: - ht = Z_OBJ_HT_P(obj)->get_properties(obj); + ht = obj->handlers->get_properties(obj); if (ht && !(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_ADDREF(ht); } @@ -1887,11 +1874,13 @@ ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose pur } ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose) { - if (Z_OBJ_HT_P(obj)->get_properties_for) { - return Z_OBJ_HT_P(obj)->get_properties_for(obj, purpose); + zend_object *zobj = Z_OBJ_P(obj); + + if (zobj->handlers->get_properties_for) { + return zobj->handlers->get_properties_for(zobj, purpose); } - return zend_std_get_properties_for(obj, purpose); + return zend_std_get_properties_for(zobj, purpose); } ZEND_API const zend_object_handlers std_object_handlers = { @@ -1906,24 +1895,20 @@ ZEND_API const zend_object_handlers std_object_handlers = { zend_std_read_dimension, /* read_dimension */ zend_std_write_dimension, /* write_dimension */ zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */ - NULL, /* get */ - NULL, /* set */ zend_std_has_property, /* has_property */ zend_std_unset_property, /* unset_property */ zend_std_has_dimension, /* has_dimension */ zend_std_unset_dimension, /* unset_dimension */ zend_std_get_properties, /* get_properties */ zend_std_get_method, /* get_method */ - NULL, /* call_method */ zend_std_get_constructor, /* get_constructor */ zend_std_get_class_name, /* get_class_name */ - zend_std_compare_objects, /* compare_objects */ zend_std_cast_object_tostring, /* cast_object */ NULL, /* count_elements */ zend_std_get_debug_info, /* get_debug_info */ zend_std_get_closure, /* get_closure */ zend_std_get_gc, /* get_gc */ NULL, /* do_operation */ - NULL, /* compare */ + zend_std_compare_objects, /* compare */ NULL, /* get_properties_for */ }; diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 770a67cbdd..19b7ff993f 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -41,10 +41,10 @@ struct _zend_property_info; symbol table, its reference count should be 0. */ /* Used to fetch property from the object, read-only */ -typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type, void **cache_slot, zval *rv); +typedef zval *(*zend_object_read_property_t)(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); /* Used to fetch dimension from the object, read-only */ -typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int type, zval *rv); +typedef zval *(*zend_object_read_dimension_t)(zend_object *object, zval *offset, int type, zval *rv); /* The following rule applies to write_property() and write_dimension() implementations: @@ -54,23 +54,14 @@ typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int ty You must return the final value of the assigned property. */ /* Used to set property of the object */ -typedef zval *(*zend_object_write_property_t)(zval *object, zval *member, zval *value, void **cache_slot); +typedef zval *(*zend_object_write_property_t)(zend_object *object, zend_string *member, zval *value, void **cache_slot); /* Used to set dimension of the object */ -typedef void (*zend_object_write_dimension_t)(zval *object, zval *offset, zval *value); +typedef void (*zend_object_write_dimension_t)(zend_object *object, zval *offset, zval *value); /* Used to create pointer to the property of the object, for future direct r/w access */ -typedef zval *(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member, int type, void **cache_slot); - -/* Used to set object value. Can be used to override assignments and scalar - write ops (like ++, +=) on the object */ -typedef void (*zend_object_set_t)(zval *object, zval *value); - -/* Used to get object value. Can be used when converting object value to - * one of the basic types and when using scalar ops (like ++, +=) on the object - */ -typedef zval* (*zend_object_get_t)(zval *object, zval *rv); +typedef zval *(*zend_object_get_property_ptr_ptr_t)(zend_object *object, zend_string *member, int type, void **cache_slot); /* Used to check if a property of the object exists */ /* param has_set_exists: @@ -78,21 +69,21 @@ typedef zval* (*zend_object_get_t)(zval *object, zval *rv); * 1 (set) whether property exists and is true * 2 (exists) whether property exists */ -typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists, void **cache_slot); +typedef int (*zend_object_has_property_t)(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot); /* Used to check if a dimension of the object exists */ -typedef int (*zend_object_has_dimension_t)(zval *object, zval *member, int check_empty); +typedef int (*zend_object_has_dimension_t)(zend_object *object, zval *member, int check_empty); /* Used to remove a property of the object */ -typedef void (*zend_object_unset_property_t)(zval *object, zval *member, void **cache_slot); +typedef void (*zend_object_unset_property_t)(zend_object *object, zend_string *member, void **cache_slot); /* Used to remove a dimension of the object */ -typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset); +typedef void (*zend_object_unset_dimension_t)(zend_object *object, zval *offset); /* Used to get hash of the properties of the object, as hash of zval's */ -typedef HashTable *(*zend_object_get_properties_t)(zval *object); +typedef HashTable *(*zend_object_get_properties_t)(zend_object *object); -typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp); +typedef HashTable *(*zend_object_get_debug_info_t)(zend_object *object, int *is_temp); typedef enum _zend_prop_purpose { /* Used for debugging. Supersedes get_debug_info handler. */ @@ -107,47 +98,43 @@ typedef enum _zend_prop_purpose { ZEND_PROP_PURPOSE_VAR_EXPORT, /* Used for json_encode(). */ ZEND_PROP_PURPOSE_JSON, - /* array_key_exists(). Not intended for general use! */ - _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS, /* Dummy member to ensure that "default" is specified. */ _ZEND_PROP_PURPOSE_NON_EXHAUSTIVE_ENUM } zend_prop_purpose; /* The return value must be released using zend_release_properties(). */ -typedef zend_array *(*zend_object_get_properties_for_t)(zval *object, zend_prop_purpose purpose); +typedef zend_array *(*zend_object_get_properties_for_t)(zend_object *object, zend_prop_purpose purpose); /* Used to call methods */ /* args on stack! */ /* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this. */ -typedef int (*zend_object_call_method_t)(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS); typedef zend_function *(*zend_object_get_method_t)(zend_object **object, zend_string *method, const zval *key); typedef zend_function *(*zend_object_get_constructor_t)(zend_object *object); /* Object maintenance/destruction */ typedef void (*zend_object_dtor_obj_t)(zend_object *object); typedef void (*zend_object_free_obj_t)(zend_object *object); -typedef zend_object* (*zend_object_clone_obj_t)(zval *object); +typedef zend_object* (*zend_object_clone_obj_t)(zend_object *object); /* Get class name for display in var_dump and other debugging functions. * Must be defined and must return a non-NULL value. */ typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object); typedef int (*zend_object_compare_t)(zval *object1, zval *object2); -typedef int (*zend_object_compare_zvals_t)(zval *result, zval *op1, zval *op2); /* Cast an object to some other type. * readobj and retval must point to distinct zvals. */ -typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type); +typedef int (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); /* updates *count to hold the number of elements present and returns SUCCESS. * Returns FAILURE if the object does not have any sense of overloaded dimensions */ -typedef int (*zend_object_count_elements_t)(zval *object, zend_long *count); +typedef int (*zend_object_count_elements_t)(zend_object *object, zend_long *count); -typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); +typedef int (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only); -typedef HashTable *(*zend_object_get_gc_t)(zval *object, zval **table, int *n); +typedef HashTable *(*zend_object_get_gc_t)(zend_object *object, zval **table, int *n); typedef int (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval *op1, zval *op2); @@ -163,25 +150,21 @@ struct _zend_object_handlers { zend_object_read_dimension_t read_dimension; /* required */ zend_object_write_dimension_t write_dimension; /* required */ zend_object_get_property_ptr_ptr_t get_property_ptr_ptr; /* required */ - zend_object_get_t get; /* optional */ - zend_object_set_t set; /* optional */ zend_object_has_property_t has_property; /* required */ zend_object_unset_property_t unset_property; /* required */ zend_object_has_dimension_t has_dimension; /* required */ zend_object_unset_dimension_t unset_dimension; /* required */ zend_object_get_properties_t get_properties; /* required */ zend_object_get_method_t get_method; /* required */ - zend_object_call_method_t call_method; /* optional */ zend_object_get_constructor_t get_constructor; /* required */ zend_object_get_class_name_t get_class_name; /* required */ - zend_object_compare_t compare_objects; /* optional */ zend_object_cast_t cast_object; /* optional */ zend_object_count_elements_t count_elements; /* optional */ zend_object_get_debug_info_t get_debug_info; /* optional */ zend_object_get_closure_t get_closure; /* optional */ zend_object_get_gc_t get_gc; /* required */ zend_object_do_operation_t do_operation; /* optional */ - zend_object_compare_zvals_t compare; /* optional */ + zend_object_compare_t compare; /* required */ zend_object_get_properties_for_t get_properties_for; /* optional */ }; @@ -205,23 +188,23 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p ZEND_API ZEND_COLD zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name); ZEND_API zend_function *zend_std_get_constructor(zend_object *object); ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent); -ZEND_API HashTable *zend_std_get_properties(zval *object); -ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n); -ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp); -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type); -ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot); -ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv); -ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot); -ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot); -ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_slot); -ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv); -ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value); -ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty); -ZEND_API void zend_std_unset_dimension(zval *object, zval *offset); +ZEND_API HashTable *zend_std_get_properties(zend_object *object); +ZEND_API HashTable *zend_std_get_gc(zend_object *object, zval **table, int *n); +ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp); +ZEND_API int zend_std_cast_object_tostring(zend_object *object, zval *writeobj, int type); +ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot); +ZEND_API zval *zend_std_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); +ZEND_API zval *zend_std_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot); +ZEND_API int zend_std_has_property(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot); +ZEND_API void zend_std_unset_property(zend_object *object, zend_string *member, void **cache_slot); +ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int type, zval *rv); +ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval *value); +ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check_empty); +ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset); ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key); ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj); ZEND_API int zend_std_compare_objects(zval *o1, zval *o2); -ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); +ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only); ZEND_API void rebuild_object_properties(zend_object *zobj); ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); @@ -234,7 +217,7 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe /* Default behavior for get_properties_for. For use as a fallback in custom * get_properties_for implementations. */ -ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose purpose); +ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purpose purpose); /* Will call get_properties_for handler or use default behavior. For use by * consumers of the get_properties_for API. */ @@ -254,6 +237,16 @@ ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose } \ } while (0) +/* Fallback to default comparison implementation if the arguments aren't both objects + * and have the same compare() handler. You'll likely want to use this unless you + * explicitly wish to support comparisons between objects and non-objects. */ +#define ZEND_COMPARE_OBJECTS_FALLBACK(op1, op2) \ + if (Z_TYPE_P(op1) != IS_OBJECT || \ + Z_TYPE_P(op2) != IS_OBJECT || \ + Z_OBJ_HT_P(op1)->compare != Z_OBJ_HT_P(op2)->compare) { \ + return zend_std_compare_objects(op1, op2); \ + } + END_EXTERN_C() #endif diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index ac9412a1c6..13a6b45a7c 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -63,7 +63,7 @@ ZEND_API void zend_object_std_dtor(zend_object *object) if (UNEXPECTED(Z_ISREF_P(p)) && (ZEND_DEBUG || ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(p)))) { zend_property_info *prop_info = zend_get_property_info_for_slot(object, p); - if (prop_info->type) { + if (ZEND_TYPE_IS_SET(prop_info->type)) { ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(p), prop_info); } } @@ -214,7 +214,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, if (UNEXPECTED(Z_ISREF_P(dst)) && (ZEND_DEBUG || ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(dst)))) { zend_property_info *prop_info = zend_get_property_info_for_slot(new_object, dst); - if (prop_info->type) { + if (ZEND_TYPE_IS_SET(prop_info->type)) { ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(dst), prop_info); } } @@ -290,14 +290,12 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, } } -ZEND_API zend_object *zend_objects_clone_obj(zval *zobject) +ZEND_API zend_object *zend_objects_clone_obj(zend_object *old_object) { - zend_object *old_object; zend_object *new_object; /* assume that create isn't overwritten, so when clone depends on the * overwritten one then it must itself be overwritten */ - old_object = Z_OBJ_P(zobject); new_object = zend_objects_new(old_object->ce); /* zend_objects_clone_members() expect the properties to be initialized. */ diff --git a/Zend/zend_objects.h b/Zend/zend_objects.h index cb0015599b..91d388154d 100644 --- a/Zend/zend_objects.h +++ b/Zend/zend_objects.h @@ -29,7 +29,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, ZEND_API void zend_object_std_dtor(zend_object *object); ZEND_API void zend_objects_destroy_object(zend_object *object); -ZEND_API zend_object *zend_objects_clone_obj(zval *object); +ZEND_API zend_object *zend_objects_clone_obj(zend_object *object); END_EXTERN_C() #endif /* ZEND_OBJECTS_H */ diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index b9a838e7bb..85ce701cd7 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -107,7 +107,7 @@ static inline zend_property_info *zend_get_property_info_for_slot(zend_object *o static inline zend_property_info *zend_get_typed_property_info_for_slot(zend_object *obj, zval *slot) { zend_property_info *prop_info = zend_get_property_info_for_slot(obj, slot); - if (prop_info && prop_info->type) { + if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) { return prop_info; } return NULL; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index a128f9436e..e197e9bf16 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -102,6 +102,22 @@ ZEND_API void destroy_zend_function(zend_function *function) zend_function_dtor(&tmp); } +ZEND_API void zend_type_release(zend_type type, zend_bool persistent) { + if (ZEND_TYPE_HAS_LIST(type)) { + void *entry; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), entry) { + if (ZEND_TYPE_LIST_IS_NAME(entry)) { + zend_string_release(ZEND_TYPE_LIST_GET_NAME(entry)); + } + } ZEND_TYPE_LIST_FOREACH_END(); + if (!ZEND_TYPE_USES_ARENA(type)) { + pefree(ZEND_TYPE_LIST(type), persistent); + } + } else if (ZEND_TYPE_HAS_NAME(type)) { + zend_string_release(ZEND_TYPE_NAME(type)); + } +} + void zend_free_internal_arg_info(zend_internal_function *function) { if ((function->fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) && function->arg_info) { @@ -114,9 +130,7 @@ void zend_free_internal_arg_info(zend_internal_function *function) { num_args++; } for (i = 0 ; i < num_args; i++) { - if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { - zend_string_release_ex(ZEND_TYPE_NAME(arg_info[i].type), 1); - } + zend_type_release(arg_info[i].type, /* persistent */ 1); } free(arg_info); } @@ -303,9 +317,7 @@ ZEND_API void destroy_zend_class(zval *zv) if (prop_info->doc_comment) { zend_string_release_ex(prop_info->doc_comment, 0); } - if (ZEND_TYPE_IS_NAME(prop_info->type)) { - zend_string_release(ZEND_TYPE_NAME(prop_info->type)); - } + zend_type_release(prop_info->type, /* persistent */ 0); } } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->properties_info); @@ -496,9 +508,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) if (arg_info[i].name) { zend_string_release_ex(arg_info[i].name, 0); } - if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { - zend_string_release_ex(ZEND_TYPE_NAME(arg_info[i].type), 0); - } + zend_type_release(arg_info[i].type, /* persistent */ 0); } efree(arg_info); } @@ -1065,7 +1075,6 @@ ZEND_API binary_op_type get_binary_op(int opcode) return (binary_op_type) shift_left_function; case ZEND_SR: return (binary_op_type) shift_right_function; - case ZEND_PARENTHESIZED_CONCAT: case ZEND_FAST_CONCAT: case ZEND_CONCAT: return (binary_op_type) concat_function; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 656316cc4e..a1f3024d4e 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -138,18 +138,11 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* { #define convert_object_to_type(op, dst, ctype, conv_func) \ ZVAL_UNDEF(dst); \ if (Z_OBJ_HT_P(op)->cast_object) { \ - if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) { \ + if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), dst, ctype) == FAILURE) { \ zend_error(E_RECOVERABLE_ERROR, \ "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\ zend_get_type_by_const(ctype)); \ } \ - } else if (Z_OBJ_HT_P(op)->get) { \ - zval *newop = Z_OBJ_HT_P(op)->get(op, dst); \ - if (Z_TYPE_P(newop) != IS_OBJECT) { \ - /* for safety - avoid loop */ \ - ZVAL_COPY_VALUE(dst, newop); \ - conv_func(dst); \ - } \ } /* }}} */ @@ -566,7 +559,7 @@ try_again: break; } case IS_ARRAY: - zend_error(E_NOTICE, "Array to string conversion"); + zend_error(E_WARNING, "Array to string conversion"); zval_ptr_dtor(op); ZVAL_INTERNED_STR(op, ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED)); break; @@ -574,21 +567,11 @@ try_again: zval tmp; if (Z_OBJ_HT_P(op)->cast_object) { - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) { + if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &tmp, IS_STRING) == SUCCESS) { zval_ptr_dtor(op); ZVAL_COPY_VALUE(op, &tmp); return; } - } else if (Z_OBJ_HT_P(op)->get) { - zval *z = Z_OBJ_HT_P(op)->get(op, &tmp); - if (Z_TYPE_P(z) != IS_OBJECT) { - zend_string *str = zval_get_string(z); - zval_ptr_dtor(z); - zval_ptr_dtor(op); - ZVAL_STR(op, str); - return; - } - zval_ptr_dtor(z); } if (!EG(exception)) { zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name)); @@ -886,23 +869,15 @@ try_again: return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op)); } case IS_ARRAY: - zend_error(E_NOTICE, "Array to string conversion"); + zend_error(E_WARNING, "Array to string conversion"); return (try && UNEXPECTED(EG(exception))) ? NULL : ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED); case IS_OBJECT: { zval tmp; if (Z_OBJ_HT_P(op)->cast_object) { - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) { + if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &tmp, IS_STRING) == SUCCESS) { return Z_STR(tmp); } - } else if (Z_OBJ_HT_P(op)->get) { - zval *z = Z_OBJ_HT_P(op)->get(op, &tmp); - if (Z_TYPE_P(z) != IS_OBJECT) { - zend_string *str = try ? zval_try_get_string(z) : zval_get_string(z); - zval_ptr_dtor(z); - return str; - } - zval_ptr_dtor(z); } if (!EG(exception)) { zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name)); @@ -1222,37 +1197,22 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* { } else if (!converted) { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW, pow_function); - if (EXPECTED(op1 != op2)) { - if (Z_TYPE_P(op1) == IS_ARRAY) { - if (op1 == result) { - zval_ptr_dtor(result); - } - ZVAL_LONG(result, 0); - return SUCCESS; - } else { - op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); - } - if (Z_TYPE_P(op2) == IS_ARRAY) { - if (op1 == result) { - zval_ptr_dtor(result); - } - ZVAL_LONG(result, 1L); - return SUCCESS; - } else { - op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0); + if (Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY) { + if (result != op1) { + ZVAL_UNDEF(result); } + zend_throw_error(NULL, "Unsupported operand types"); + return FAILURE; + } + + if (EXPECTED(op1 != op2)) { + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); + op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0); } else { - if (Z_TYPE_P(op1) == IS_ARRAY) { - if (op1 == result) { - zval_ptr_dtor(result); - } - ZVAL_LONG(result, 0); - return SUCCESS; - } else { - op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); - } + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); op2 = op1; } + if (EG(exception)) { if (result != op1) { ZVAL_UNDEF(result); @@ -2002,98 +1962,69 @@ ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2) /* {{{ } /* }}} */ -static zend_always_inline void zend_free_obj_get_result(zval *op) /* {{{ */ -{ - ZEND_ASSERT(!Z_REFCOUNTED_P(op) || Z_REFCOUNT_P(op) != 0); - zval_ptr_dtor(op); -} -/* }}} */ - -static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */ +ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */ { - if (Z_TYPE_P(result) == IS_DOUBLE) { - ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); - } else { - convert_to_long(result); - } + ZVAL_LONG(result, zend_compare(op1, op2)); + return SUCCESS; } /* }}} */ -ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */ +ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */ { - int ret; int converted = 0; zval op1_copy, op2_copy; - zval *op_free, tmp_free; while (1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_LONG, IS_LONG): - ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0)); - return SUCCESS; + return Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0); case TYPE_PAIR(IS_DOUBLE, IS_LONG): - Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2); - ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); - return SUCCESS; + return ZEND_NORMALIZE_BOOL(Z_DVAL_P(op1) - (double)Z_LVAL_P(op2)); case TYPE_PAIR(IS_LONG, IS_DOUBLE): - Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2); - ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); - return SUCCESS; + return ZEND_NORMALIZE_BOOL((double)Z_LVAL_P(op1) - Z_DVAL_P(op2)); case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) { - ZVAL_LONG(result, 0); + return 0; } else { - Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2); - ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); + return ZEND_NORMALIZE_BOOL(Z_DVAL_P(op1) - Z_DVAL_P(op2)); } - return SUCCESS; case TYPE_PAIR(IS_ARRAY, IS_ARRAY): - ZVAL_LONG(result, zend_compare_arrays(op1, op2)); - return SUCCESS; + return zend_compare_arrays(op1, op2); case TYPE_PAIR(IS_NULL, IS_NULL): case TYPE_PAIR(IS_NULL, IS_FALSE): case TYPE_PAIR(IS_FALSE, IS_NULL): case TYPE_PAIR(IS_FALSE, IS_FALSE): case TYPE_PAIR(IS_TRUE, IS_TRUE): - ZVAL_LONG(result, 0); - return SUCCESS; + return 0; case TYPE_PAIR(IS_NULL, IS_TRUE): - ZVAL_LONG(result, -1); - return SUCCESS; + return -1; case TYPE_PAIR(IS_TRUE, IS_NULL): - ZVAL_LONG(result, 1); - return SUCCESS; + return 1; case TYPE_PAIR(IS_STRING, IS_STRING): if (Z_STR_P(op1) == Z_STR_P(op2)) { - ZVAL_LONG(result, 0); - return SUCCESS; + return 0; } - ZVAL_LONG(result, zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2))); - return SUCCESS; + return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)); case TYPE_PAIR(IS_NULL, IS_STRING): - ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1); - return SUCCESS; + return Z_STRLEN_P(op2) == 0 ? 0 : -1; case TYPE_PAIR(IS_STRING, IS_NULL): - ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1); - return SUCCESS; + return Z_STRLEN_P(op1) == 0 ? 0 : 1; case TYPE_PAIR(IS_OBJECT, IS_NULL): - ZVAL_LONG(result, 1); - return SUCCESS; + return 1; case TYPE_PAIR(IS_NULL, IS_OBJECT): - ZVAL_LONG(result, -1); - return SUCCESS; + return -1; default: if (Z_ISREF_P(op1)) { @@ -2104,109 +2035,41 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) continue; } - if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) { - ret = Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2); - if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) { - convert_compare_result_to_long(result); - } - return ret; - } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) { - ret = Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2); - if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) { - convert_compare_result_to_long(result); - } - return ret; + if (Z_TYPE_P(op1) == IS_OBJECT + && Z_TYPE_P(op2) == IS_OBJECT + && Z_OBJ_P(op1) == Z_OBJ_P(op2)) { + return 0; + } else if (Z_TYPE_P(op1) == IS_OBJECT) { + return Z_OBJ_HANDLER_P(op1, compare)(op1, op2); + } else if (Z_TYPE_P(op2) == IS_OBJECT) { + return Z_OBJ_HANDLER_P(op2, compare)(op1, op2); } - if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) { - if (Z_OBJ_P(op1) == Z_OBJ_P(op2)) { - /* object handles are identical, apparently this is the same object */ - ZVAL_LONG(result, 0); - return SUCCESS; - } - if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) { - ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2)); - return SUCCESS; - } - } - if (Z_TYPE_P(op1) == IS_OBJECT) { - if (Z_OBJ_HT_P(op1)->get) { - zval rv; - op_free = Z_OBJ_HT_P(op1)->get(op1, &rv); - ret = compare_function(result, op_free, op2); - zend_free_obj_get_result(op_free); - return ret; - } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { - ZVAL_UNDEF(&tmp_free); - if (Z_OBJ_HT_P(op1)->cast_object(op1, &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) { - ZVAL_LONG(result, 1); - zend_free_obj_get_result(&tmp_free); - return SUCCESS; - } - ret = compare_function(result, &tmp_free, op2); - zend_free_obj_get_result(&tmp_free); - return ret; - } - } - if (Z_TYPE_P(op2) == IS_OBJECT) { - if (Z_OBJ_HT_P(op2)->get) { - zval rv; - op_free = Z_OBJ_HT_P(op2)->get(op2, &rv); - ret = compare_function(result, op1, op_free); - zend_free_obj_get_result(op_free); - return ret; - } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { - ZVAL_UNDEF(&tmp_free); - if (Z_OBJ_HT_P(op2)->cast_object(op2, &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) { - ZVAL_LONG(result, -1); - zend_free_obj_get_result(&tmp_free); - return SUCCESS; - } - ret = compare_function(result, op1, &tmp_free); - zend_free_obj_get_result(&tmp_free); - return ret; - } else if (Z_TYPE_P(op1) == IS_OBJECT) { - ZVAL_LONG(result, 1); - return SUCCESS; - } - } if (!converted) { if (Z_TYPE_P(op1) < IS_TRUE) { - ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0); - return SUCCESS; + return zval_is_true(op2) ? -1 : 0; } else if (Z_TYPE_P(op1) == IS_TRUE) { - ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1); - return SUCCESS; + return zval_is_true(op2) ? 0 : 1; } else if (Z_TYPE_P(op2) < IS_TRUE) { - ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0); - return SUCCESS; + return zval_is_true(op1) ? 1 : 0; } else if (Z_TYPE_P(op2) == IS_TRUE) { - ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1); - return SUCCESS; + return zval_is_true(op1) ? 0 : -1; } else { - op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 1); - op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 1); + op1 = _zendi_convert_scalar_to_number(op1, &op1_copy); + op2 = _zendi_convert_scalar_to_number(op2, &op2_copy); if (EG(exception)) { - if (result != op1) { - ZVAL_UNDEF(result); - } - return FAILURE; + return 1; /* to stop comparison of arrays */ } converted = 1; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { - ZVAL_LONG(result, 1); - return SUCCESS; + return 1; } else if (Z_TYPE_P(op2)==IS_ARRAY) { - ZVAL_LONG(result, -1); - return SUCCESS; + return -1; } else { ZEND_ASSERT(0); zend_throw_error(NULL, "Unsupported operand types"); - if (result != op1) { - ZVAL_UNDEF(result); - } - return FAILURE; + return 1; } } } @@ -2271,91 +2134,75 @@ ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zv ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */ { - if (compare_function(result, op1, op2) == FAILURE) { - return FAILURE; - } - ZVAL_BOOL(result, (Z_LVAL_P(result) == 0)); + ZVAL_BOOL(result, zend_compare(op1, op2) == 0); return SUCCESS; } /* }}} */ ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */ { - if (compare_function(result, op1, op2) == FAILURE) { - return FAILURE; - } - ZVAL_BOOL(result, (Z_LVAL_P(result) != 0)); + ZVAL_BOOL(result, (zend_compare(op1, op2) != 0)); return SUCCESS; } /* }}} */ ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2) /* {{{ */ { - if (compare_function(result, op1, op2) == FAILURE) { - return FAILURE; - } - ZVAL_BOOL(result, (Z_LVAL_P(result) < 0)); + ZVAL_BOOL(result, (zend_compare(op1, op2) < 0)); return SUCCESS; } /* }}} */ ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */ { - if (compare_function(result, op1, op2) == FAILURE) { - return FAILURE; - } - ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0)); + ZVAL_BOOL(result, (zend_compare(op1, op2) <= 0)); return SUCCESS; } /* }}} */ -static zend_always_inline zend_bool instanceof_class(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ -{ - do { - if (instance_ce == ce) { - return 1; - } - instance_ce = instance_ce->parent; - } while (instance_ce); - return 0; -} -/* }}} */ - -static zend_bool ZEND_FASTCALL instanceof_interface(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ +ZEND_API zend_bool ZEND_FASTCALL zend_class_implements_interface(const zend_class_entry *class_ce, const zend_class_entry *interface_ce) /* {{{ */ { uint32_t i; + ZEND_ASSERT(!(class_ce->ce_flags & ZEND_ACC_INTERFACE)); + ZEND_ASSERT(interface_ce->ce_flags & ZEND_ACC_INTERFACE); - if (instance_ce->num_interfaces) { - ZEND_ASSERT(instance_ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); - for (i = 0; i < instance_ce->num_interfaces; i++) { - if (instance_ce->interfaces[i] == ce) { + if (class_ce->num_interfaces) { + ZEND_ASSERT(class_ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); + for (i = 0; i < class_ce->num_interfaces; i++) { + if (class_ce->interfaces[i] == interface_ce) { return 1; } } } - return instance_ce == ce; -} -/* }}} */ - -// TODO: It would make more sense to expose instanceof_class + instanceof_interface instead -ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool is_interface) /* {{{ */ -{ - if (is_interface) { - ZEND_ASSERT(ce->ce_flags & ZEND_ACC_INTERFACE); - return instanceof_interface(instance_ce, ce); - } else { - ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_INTERFACE)); - return instanceof_class(instance_ce, ce); - } + return 0; } /* }}} */ -ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ +ZEND_API zend_bool ZEND_FASTCALL instanceof_function_slow(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ { + ZEND_ASSERT(instance_ce != ce && "Should have been checked already"); if (ce->ce_flags & ZEND_ACC_INTERFACE) { - return instanceof_interface(instance_ce, ce); + uint32_t i; + + if (instance_ce->num_interfaces) { + ZEND_ASSERT(instance_ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); + for (i = 0; i < instance_ce->num_interfaces; i++) { + if (instance_ce->interfaces[i] == ce) { + return 1; + } + } + } + return 0; } else { - return instanceof_class(instance_ce, ce); + while (1) { + instance_ce = instance_ce->parent; + if (instance_ce == ce) { + return 1; + } + if (instance_ce == NULL) { + return 0; + } + } } } /* }}} */ @@ -2489,18 +2336,7 @@ try_again: } break; case IS_OBJECT: - if (Z_OBJ_HANDLER_P(op1, get) - && Z_OBJ_HANDLER_P(op1, set)) { - /* proxy object */ - zval rv; - zval *val; - - val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv); - Z_TRY_ADDREF_P(val); - increment_function(val); - Z_OBJ_HANDLER_P(op1, set)(op1, val); - zval_ptr_dtor(val); - } else if (Z_OBJ_HANDLER_P(op1, do_operation)) { + if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; int res; @@ -2556,18 +2392,7 @@ try_again: } break; case IS_OBJECT: - if (Z_OBJ_HANDLER_P(op1, get) - && Z_OBJ_HANDLER_P(op1, set)) { - /* proxy object */ - zval rv; - zval *val; - - val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv); - Z_TRY_ADDREF_P(val); - decrement_function(val); - Z_OBJ_HANDLER_P(op1, set)(op1, val); - zval_ptr_dtor(val); - } else if (Z_OBJ_HANDLER_P(op1, do_operation)) { + if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; int res; @@ -2596,23 +2421,14 @@ ZEND_API int ZEND_FASTCALL zend_is_true(zval *op) /* {{{ */ ZEND_API int ZEND_FASTCALL zend_object_is_true(zval *op) /* {{{ */ { - if (Z_OBJ_HT_P(op)->cast_object) { + zend_object *zobj = Z_OBJ_P(op); + + if (zobj->handlers->cast_object) { zval tmp; - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL) == SUCCESS) { + if (zobj->handlers->cast_object(zobj, &tmp, _IS_BOOL) == SUCCESS) { return Z_TYPE(tmp) == IS_TRUE; } - zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to bool", ZSTR_VAL(Z_OBJ_P(op)->ce->name)); - } else if (Z_OBJ_HT_P(op)->get) { - int result; - zval rv; - zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv); - - if (Z_TYPE_P(tmp) != IS_OBJECT) { - /* for safety - avoid loop */ - result = i_zend_is_true(tmp); - zval_ptr_dtor(tmp); - return result; - } + zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to bool", ZSTR_VAL(zobj->ce->name)); } return 1; } @@ -2958,12 +2774,7 @@ string_cmp: static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */ { - zval result; - - if (compare_function(&result, z1, z2)==FAILURE) { - return 1; - } - return Z_LVAL(result); + return zend_compare(z1, z2); } /* }}} */ @@ -2985,10 +2796,10 @@ ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2) /* {{{ */ return 0; } - if (Z_OBJ_HT_P(o1)->compare_objects == NULL) { + if (Z_OBJ_HT_P(o1)->compare == NULL) { return 1; } else { - return Z_OBJ_HT_P(o1)->compare_objects(o1, o2); + return Z_OBJ_HT_P(o1)->compare(o1, o2); } } /* }}} */ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 1ca1c7751c..ee7c951c7d 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -63,8 +63,13 @@ ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval * ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2); -ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool is_interface); -ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce); +ZEND_API zend_bool ZEND_FASTCALL zend_class_implements_interface(const zend_class_entry *class_ce, const zend_class_entry *interface_ce); +ZEND_API zend_bool ZEND_FASTCALL instanceof_function_slow(const zend_class_entry *instance_ce, const zend_class_entry *ce); + +static zend_always_inline zend_bool instanceof_function( + const zend_class_entry *instance_ce, const zend_class_entry *ce) { + return instance_ce == ce || instanceof_function_slow(instance_ce, ce); +} /** * Checks whether the string "str" with length "length" is numeric. The value @@ -148,10 +153,13 @@ static zend_always_inline const char * zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const char *end) { const char *p = haystack; - const char ne = needle[needle_len-1]; ptrdiff_t off_p; size_t off_s; + if (needle_len == 0) { + return p; + } + if (needle_len == 1) { return (const char *)memchr(p, *needle, (end-p)); } @@ -164,6 +172,7 @@ zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const } if (EXPECTED(off_s < 1024 || needle_len < 9)) { /* glibc memchr is faster when needle is too short */ + const char ne = needle[needle_len-1]; end -= needle_len; while (p <= end) { @@ -206,10 +215,13 @@ static zend_always_inline const char * zend_memnrstr(const char *haystack, const char *needle, size_t needle_len, const char *end) { const char *p = end; - const char ne = needle[needle_len-1]; ptrdiff_t off_p; size_t off_s; + if (needle_len == 0) { + return p; + } + if (needle_len == 1) { return (const char *)zend_memrchr(haystack, *needle, (p - haystack)); } @@ -222,6 +234,7 @@ zend_memnrstr(const char *haystack, const char *needle, size_t needle_len, const } if (EXPECTED(off_s < 1024 || needle_len < 3)) { + const char ne = needle[needle_len-1]; p -= needle_len; do { @@ -388,6 +401,8 @@ again: return result; } +ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2); + ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2); @@ -500,9 +515,15 @@ ZEND_API void zend_update_current_locale(void); #define ZVAL_OFFSETOF_TYPE \ (offsetof(zval, u1.type_info) - offsetof(zval, value)) +#if defined(HAVE_ASM_GOTO) && !__has_feature(memory_sanitizer) +# define ZEND_USE_ASM_ARITHMETIC 1 +#else +# define ZEND_USE_ASM_ARITHMETIC 0 +#endif + static zend_always_inline void fast_long_increment_function(zval *op1) { -#if defined(HAVE_ASM_GOTO) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) +#if ZEND_USE_ASM_ARITHMETIC && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) __asm__ goto( "addl $1,(%0)\n\t" "jo %l1\n" @@ -513,7 +534,7 @@ static zend_always_inline void fast_long_increment_function(zval *op1) return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0); -#elif defined(HAVE_ASM_GOTO) && defined(__x86_64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__x86_64__) __asm__ goto( "addq $1,(%0)\n\t" "jo %l1\n" @@ -524,7 +545,7 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0); -#elif defined(HAVE_ASM_GOTO) && defined(__aarch64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__aarch64__) __asm__ goto ( "ldr x5, [%0]\n\t" "adds x5, x5, 1\n\t" @@ -565,7 +586,7 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL static zend_always_inline void fast_long_decrement_function(zval *op1) { -#if defined(HAVE_ASM_GOTO) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) +#if ZEND_USE_ASM_ARITHMETIC && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) __asm__ goto( "subl $1,(%0)\n\t" "jo %l1\n" @@ -576,7 +597,7 @@ static zend_always_inline void fast_long_decrement_function(zval *op1) return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0); -#elif defined(HAVE_ASM_GOTO) && defined(__x86_64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__x86_64__) __asm__ goto( "subq $1,(%0)\n\t" "jo %l1\n" @@ -587,7 +608,7 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0); -#elif defined(HAVE_ASM_GOTO) && defined(__aarch64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__aarch64__) __asm__ goto ( "ldr x5, [%0]\n\t" "subs x5 ,x5, 1\n\t" @@ -628,7 +649,7 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL static zend_always_inline void fast_long_add_function(zval *result, zval *op1, zval *op2) { -#if defined(HAVE_ASM_GOTO) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) +#if ZEND_USE_ASM_ARITHMETIC && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) __asm__ goto( "movl (%1), %%eax\n\t" "addl (%2), %%eax\n\t" @@ -646,7 +667,7 @@ static zend_always_inline void fast_long_add_function(zval *result, zval *op1, z return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2)); -#elif defined(HAVE_ASM_GOTO) && defined(__x86_64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__x86_64__) __asm__ goto( "movq (%1), %%rax\n\t" "addq (%2), %%rax\n\t" @@ -664,7 +685,7 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2)); -#elif defined(HAVE_ASM_GOTO) && defined(__aarch64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__aarch64__) __asm__ goto( "ldr x5, [%1]\n\t" "ldr x6, [%2]\n\t" @@ -738,7 +759,7 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o static zend_always_inline void fast_long_sub_function(zval *result, zval *op1, zval *op2) { -#if defined(HAVE_ASM_GOTO) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) +#if ZEND_USE_ASM_ARITHMETIC && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__) __asm__ goto( "movl (%1), %%eax\n\t" "subl (%2), %%eax\n\t" @@ -756,7 +777,7 @@ static zend_always_inline void fast_long_sub_function(zval *result, zval *op1, z return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2)); -#elif defined(HAVE_ASM_GOTO) && defined(__x86_64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__x86_64__) __asm__ goto( "movq (%1), %%rax\n\t" "subq (%2), %%rax\n\t" @@ -774,7 +795,7 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL return; overflow: ZEND_ATTRIBUTE_COLD_LABEL ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2)); -#elif defined(HAVE_ASM_GOTO) && defined(__aarch64__) +#elif ZEND_USE_ASM_ARITHMETIC && defined(__aarch64__) __asm__ goto( "ldr x5, [%1]\n\t" "ldr x6, [%2]\n\t" @@ -836,7 +857,6 @@ static zend_always_inline int zend_fast_equal_strings(zend_string *s1, zend_stri static zend_always_inline int fast_equal_check_function(zval *op1, zval *op2) { - zval result; if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { return Z_LVAL_P(op1) == Z_LVAL_P(op2); @@ -854,28 +874,23 @@ static zend_always_inline int fast_equal_check_function(zval *op1, zval *op2) return zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); } } - compare_function(&result, op1, op2); - return Z_LVAL(result) == 0; + return zend_compare(op1, op2) == 0; } static zend_always_inline int fast_equal_check_long(zval *op1, zval *op2) { - zval result; if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { return Z_LVAL_P(op1) == Z_LVAL_P(op2); } - compare_function(&result, op1, op2); - return Z_LVAL(result) == 0; + return zend_compare(op1, op2) == 0; } static zend_always_inline int fast_equal_check_string(zval *op1, zval *op2) { - zval result; if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { return zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); } - compare_function(&result, op1, op2); - return Z_LVAL(result) == 0; + return zend_compare(op1, op2) == 0; } static zend_always_inline zend_bool fast_is_identical_function(zval *op1, zval *op2) @@ -899,19 +914,7 @@ static zend_always_inline zend_bool fast_is_not_identical_function(zval *op1, zv } #define ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode, binary_op) \ - if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ - && op1 == result \ - && UNEXPECTED(Z_OBJ_HANDLER_P(op1, get)) \ - && EXPECTED(Z_OBJ_HANDLER_P(op1, set))) { \ - int ret; \ - zval rv; \ - zval *objval = Z_OBJ_HANDLER_P(op1, get)(op1, &rv); \ - Z_TRY_ADDREF_P(objval); \ - ret = binary_op(objval, objval, op2); \ - Z_OBJ_HANDLER_P(op1, set)(op1, objval); \ - zval_ptr_dtor(objval); \ - return ret; \ - } else if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ + if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ && UNEXPECTED(Z_OBJ_HANDLER_P(op1, do_operation))) { \ if (EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2))) { \ return SUCCESS; \ diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index dd518aebbb..2495273d1d 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -438,49 +438,23 @@ char *alloca(); #define ZEND_BIT_TEST(bits, bit) \ (((bits)[(bit) / (sizeof((bits)[0])*8)] >> ((bit) & (sizeof((bits)[0])*8-1))) & 1) -/* We always define a function, even if there's a macro or expression we could - * alias, so that using it in contexts where we can't make function calls - * won't fail to compile on some machines and not others. - */ -static zend_always_inline double _zend_get_inf(void) /* {{{ */ -{ -#ifdef INFINITY - return INFINITY; -#elif HAVE_HUGE_VAL_INF - return HUGE_VAL; -#elif defined(__i386__) || defined(_X86_) || defined(ALPHA) || defined(_ALPHA) || defined(__alpha) -# define _zend_DOUBLE_INFINITY_HIGH 0x7ff00000 - double val = 0.0; - ((uint32_t*)&val)[1] = _zend_DOUBLE_INFINITY_HIGH; - ((uint32_t*)&val)[0] = 0; - return val; -#elif HAVE_ATOF_ACCEPTS_INF - return atof("INF"); -#else - return 1.0/0.0; -#endif -} /* }}} */ -#define ZEND_INFINITY (_zend_get_inf()) - -static zend_always_inline double _zend_get_nan(void) /* {{{ */ -{ -#ifdef NAN - return NAN; -#elif HAVE_HUGE_VAL_NAN - return HUGE_VAL + -HUGE_VAL; -#elif defined(__i386__) || defined(_X86_) || defined(ALPHA) || defined(_ALPHA) || defined(__alpha) -# define _zend_DOUBLE_QUIET_NAN_HIGH 0xfff80000 - double val = 0.0; - ((uint32_t*)&val)[1] = _zend_DOUBLE_QUIET_NAN_HIGH; - ((uint32_t*)&val)[0] = 0; - return val; -#elif HAVE_ATOF_ACCEPTS_NAN - return atof("NAN"); -#else - return 0.0/0.0; -#endif -} /* }}} */ -#define ZEND_NAN (_zend_get_nan()) +#define ZEND_INFINITY INFINITY + +#define ZEND_NAN NAN + +#if defined(__cplusplus) && __cplusplus >= 201103L +extern "C++" { +# include <cmath> +} +# define zend_isnan std::isnan +# define zend_isinf std::isinf +# define zend_finite std::isfinite +#else +# include <math.h> +# define zend_isnan(a) isnan(a) +# define zend_isinf(a) isinf(a) +# define zend_finite(a) isfinite(a) +#endif #define ZEND_STRL(str) (str), (sizeof(str)-1) #define ZEND_STRS(str) (str), (sizeof(str)) diff --git a/Zend/zend_smart_str.c b/Zend/zend_smart_str.c index 1a5eb455ad..3916902e8d 100644 --- a/Zend/zend_smart_str.c +++ b/Zend/zend_smart_str.c @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | diff --git a/Zend/zend_smart_str.h b/Zend/zend_smart_str.h index 2dab1f809a..9211e54bee 100644 --- a/Zend/zend_smart_str.h +++ b/Zend/zend_smart_str.h @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | diff --git a/Zend/zend_smart_str_public.h b/Zend/zend_smart_str_public.h index ba0b399881..eef4a7100a 100644 --- a/Zend/zend_smart_str_public.h +++ b/Zend/zend_smart_str_public.h @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | diff --git a/Zend/zend_smart_string.h b/Zend/zend_smart_string.h index 4580e43769..1f74a63218 100644 --- a/Zend/zend_smart_string.h +++ b/Zend/zend_smart_string.h @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | diff --git a/Zend/zend_smart_string_public.h b/Zend/zend_smart_string_public.h index e39d67c16e..c575d514ce 100644 --- a/Zend/zend_smart_string_public.h +++ b/Zend/zend_smart_string_public.h @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | diff --git a/Zend/zend_string.h b/Zend/zend_string.h index b4a0ddef95..f2076beee1 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -480,7 +480,6 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_THIS, "this") \ _(ZEND_STR_VALUE, "value") \ _(ZEND_STR_KEY, "key") \ - _(ZEND_STR_MAGIC_AUTOLOAD, "__autoload") \ _(ZEND_STR_MAGIC_INVOKE, "__invoke") \ _(ZEND_STR_PREVIOUS, "previous") \ _(ZEND_STR_CODE, "code") \ @@ -507,6 +506,14 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_ARGV, "argv") \ _(ZEND_STR_ARGC, "argc") \ _(ZEND_STR_ARRAY_CAPITALIZED, "Array") \ + _(ZEND_STR_BOOL, "bool") \ + _(ZEND_STR_INT, "int") \ + _(ZEND_STR_FLOAT, "float") \ + _(ZEND_STR_CALLABLE, "callable") \ + _(ZEND_STR_ITERABLE, "iterable") \ + _(ZEND_STR_VOID, "void") \ + _(ZEND_STR_FALSE, "false") \ + _(ZEND_STR_NULL_LOWERCASE, "null") \ typedef enum _zend_known_string_id { diff --git a/Zend/zend_ts_hash.c b/Zend/zend_ts_hash.c index 3cff54bf6c..6b69b49e15 100644 --- a/Zend/zend_ts_hash.c +++ b/Zend/zend_ts_hash.c @@ -264,15 +264,11 @@ ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, co end_read(source); } -ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber) +ZEND_API void zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber) { - int retval; - begin_write(ht); - retval = zend_hash_sort_ex(TS_HASH(ht), sort_func, compare_func, renumber); + zend_hash_sort_ex(TS_HASH(ht), sort_func, compare_func, renumber); end_write(ht); - - return retval; } ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered) @@ -310,15 +306,11 @@ ZEND_API int zend_ts_hash_num_elements(TsHashTable *ht) return retval; } -ZEND_API int zend_ts_hash_rehash(TsHashTable *ht) +ZEND_API void zend_ts_hash_rehash(TsHashTable *ht) { - int retval; - begin_write(ht); - retval = zend_hash_rehash(TS_HASH(ht)); + zend_hash_rehash(TS_HASH(ht)); end_write(ht); - - return retval; } ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, size_t len) diff --git a/Zend/zend_ts_hash.h b/Zend/zend_ts_hash.h index 35a4250d34..88aa4d45f4 100644 --- a/Zend/zend_ts_hash.h +++ b/Zend/zend_ts_hash.h @@ -73,13 +73,13 @@ ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_c ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor); ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite); ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam); -ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber); +ZEND_API void zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber); ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered); ZEND_API zval *zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag); ZEND_API int zend_ts_hash_num_elements(TsHashTable *ht); -ZEND_API int zend_ts_hash_rehash(TsHashTable *ht); +ZEND_API void zend_ts_hash_rehash(TsHashTable *ht); #if ZEND_DEBUG /* debug */ diff --git a/Zend/zend_type_info.h b/Zend/zend_type_info.h index 72550b6fc3..ef2c6a19bc 100644 --- a/Zend/zend_type_info.h +++ b/Zend/zend_type_info.h @@ -25,6 +25,7 @@ #define MAY_BE_NULL (1 << IS_NULL) #define MAY_BE_FALSE (1 << IS_FALSE) #define MAY_BE_TRUE (1 << IS_TRUE) +#define MAY_BE_BOOL (MAY_BE_FALSE|MAY_BE_TRUE) #define MAY_BE_LONG (1 << IS_LONG) #define MAY_BE_DOUBLE (1 << IS_DOUBLE) #define MAY_BE_STRING (1 << IS_STRING) @@ -34,7 +35,12 @@ #define MAY_BE_ANY (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE) #define MAY_BE_REF (1 << IS_REFERENCE) /* may be reference */ -#define MAY_BE_ARRAY_SHIFT (IS_REFERENCE) +/* These are used in zend_type, but not for type inference. */ +#define MAY_BE_CALLABLE (1 << IS_CALLABLE) +#define MAY_BE_ITERABLE (1 << IS_ITERABLE) +#define MAY_BE_VOID (1 << IS_VOID) + +#define MAY_BE_ARRAY_SHIFT (IS_VOID) #define MAY_BE_ARRAY_OF_NULL (MAY_BE_NULL << MAY_BE_ARRAY_SHIFT) #define MAY_BE_ARRAY_OF_FALSE (MAY_BE_FALSE << MAY_BE_ARRAY_SHIFT) @@ -48,11 +54,11 @@ #define MAY_BE_ARRAY_OF_ANY (MAY_BE_ANY << MAY_BE_ARRAY_SHIFT) #define MAY_BE_ARRAY_OF_REF (MAY_BE_REF << MAY_BE_ARRAY_SHIFT) -#define MAY_BE_ARRAY_KEY_LONG (1<<21) -#define MAY_BE_ARRAY_KEY_STRING (1<<22) +#define MAY_BE_ARRAY_KEY_LONG (1<<25) +#define MAY_BE_ARRAY_KEY_STRING (1<<26) #define MAY_BE_ARRAY_KEY_ANY (MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_KEY_STRING) -#define MAY_BE_ERROR (1<<23) -#define MAY_BE_CLASS (1<<24) +/* Bit 27 unused */ +#define MAY_BE_CLASS (1<<28) #endif /* ZEND_TYPE_INFO_H */ diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 7b8c079c45..e32538591b 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -15,7 +15,7 @@ | Authors: Andi Gutmans <andi@php.net> | | Zeev Suraski <zeev@php.net> | | Dmitry Stogov <dmitry@php.net> | - | Xinchen Hui <xinchen.h@zend.com> | + | Xinchen Hui <laruence@php.net> | +----------------------------------------------------------------------+ */ @@ -105,73 +105,184 @@ typedef void (*copy_ctor_func_t)(zval *pElement); * zend_type - is an abstraction layer to represent information about type hint. * It shouldn't be used directly. Only through ZEND_TYPE_* macros. * - * ZEND_TYPE_IS_SET() - checks if type-hint exists - * ZEND_TYPE_IS_CODE() - checks if type-hint refer to standard type - * ZEND_TYPE_IS_CLASS() - checks if type-hint refer to some class - * ZEND_TYPE_IS_CE() - checks if type-hint refer to some class by zend_class_entry * - * ZEND_TYPE_IS_NAME() - checks if type-hint refer to some class by zend_string * + * ZEND_TYPE_IS_SET() - checks if there is a type-hint + * ZEND_TYPE_HAS_ONLY_MASK() - checks if type-hint refer to standard type only + * ZEND_TYPE_HAS_CLASS() - checks if type-hint contains some class + * ZEND_TYPE_HAS_CE() - checks if type-hint contains some class as zend_class_entry * + * ZEND_TYPE_HAS_NAME() - checks if type-hint contains some class as zend_string * * * ZEND_TYPE_NAME() - returns referenced class name * ZEND_TYPE_CE() - returns referenced class entry - * ZEND_TYPE_CODE() - returns standard type code (e.g. IS_LONG, _IS_BOOL) + * ZEND_TYPE_PURE_MASK() - returns MAY_BE_* type mask + * ZEND_TYPE_FULL_MASK() - returns MAY_BE_* type mask together with other flags * * ZEND_TYPE_ALLOW_NULL() - checks if NULL is allowed * - * ZEND_TYPE_ENCODE() and ZEND_TYPE_ENCODE_CLASS() should be used for - * construction. + * ZEND_TYPE_INIT_*() should be used for construction. */ -typedef uintptr_t zend_type; +typedef struct { + /* Not using a union here, because there's no good way to initialize them + * in a way that is supported in both C and C++ (designated initializers + * are only supported since C++20). */ + void *ptr; + uint32_t type_mask; + /* TODO: We could use the extra 32-bit of padding on 64-bit systems. */ +} zend_type; + +typedef struct { + size_t num_types; + void *types[1]; +} zend_type_list; + +#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 24 +#define _ZEND_TYPE_MASK ((1u << 24) - 1) +#define _ZEND_TYPE_MAY_BE_MASK ((1u << (IS_VOID+1)) - 1) +/* Only one of these bits may be set. */ +#define _ZEND_TYPE_NAME_BIT (1u << 23) +#define _ZEND_TYPE_CE_BIT (1u << 22) +#define _ZEND_TYPE_LIST_BIT (1u << 21) +#define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_CE_BIT|_ZEND_TYPE_NAME_BIT) +/* Whether the type list is arena allocated */ +#define _ZEND_TYPE_ARENA_BIT (1u << 20) +/* Must have same value as MAY_BE_NULL */ +#define _ZEND_TYPE_NULLABLE_BIT 0x2 #define ZEND_TYPE_IS_SET(t) \ - ((t) > Z_L(0x3)) + (((t).type_mask & _ZEND_TYPE_MASK) != 0) + +#define ZEND_TYPE_HAS_CLASS(t) \ + ((((t).type_mask) & _ZEND_TYPE_KIND_MASK) != 0) + +#define ZEND_TYPE_HAS_CE(t) \ + ((((t).type_mask) & _ZEND_TYPE_CE_BIT) != 0) -#define ZEND_TYPE_IS_CODE(t) \ - (((t) > Z_L(0x3)) && ((t) <= Z_L(0x3ff))) +#define ZEND_TYPE_HAS_NAME(t) \ + ((((t).type_mask) & _ZEND_TYPE_NAME_BIT) != 0) -#define ZEND_TYPE_IS_CLASS(t) \ - ((t) > Z_L(0x3ff)) +#define ZEND_TYPE_HAS_LIST(t) \ + ((((t).type_mask) & _ZEND_TYPE_LIST_BIT) != 0) -#define ZEND_TYPE_IS_CE(t) \ - (((t) & Z_L(0x2)) != 0) +#define ZEND_TYPE_USES_ARENA(t) \ + ((((t).type_mask) & _ZEND_TYPE_ARENA_BIT) != 0) -#define ZEND_TYPE_IS_NAME(t) \ - (ZEND_TYPE_IS_CLASS(t) && !ZEND_TYPE_IS_CE(t)) +#define ZEND_TYPE_IS_ONLY_MASK(t) \ + (ZEND_TYPE_IS_SET(t) && (t).ptr == NULL) #define ZEND_TYPE_NAME(t) \ - ((zend_string*)((t) & ~Z_L(0x3))) + ((zend_string *) (t).ptr) + +#define ZEND_TYPE_LITERAL_NAME(t) \ + ((const char *) (t).ptr) #define ZEND_TYPE_CE(t) \ - ((zend_class_entry*)((t) & ~Z_L(0x3))) + ((zend_class_entry *) (t).ptr) + +#define ZEND_TYPE_LIST(t) \ + ((zend_type_list *) (t).ptr) + +/* Type lists use the low bit to distinguish NAME and CE entries, + * both of which may exist in the same list. */ +#define ZEND_TYPE_LIST_IS_CE(entry) \ + (((uintptr_t) (entry)) & 1) + +#define ZEND_TYPE_LIST_IS_NAME(entry) \ + !ZEND_TYPE_LIST_IS_CE(entry) + +#define ZEND_TYPE_LIST_GET_NAME(entry) \ + ((zend_string *) (entry)) + +#define ZEND_TYPE_LIST_GET_CE(entry) \ + ((zend_class_entry *) ((uintptr_t) (entry) & ~1)) + +#define ZEND_TYPE_LIST_ENCODE_NAME(name) \ + ((void *) (name)) + +#define ZEND_TYPE_LIST_ENCODE_CE(ce) \ + ((void *) (((uintptr_t) ce) | 1)) + +#define ZEND_TYPE_LIST_SIZE(num_types) \ + (sizeof(zend_type_list) + ((num_types) - 1) * sizeof(void *)) + +#define ZEND_TYPE_LIST_FOREACH_PTR(list, entry_ptr) do { \ + void **_list = (list)->types; \ + void **_end = _list + (list)->num_types; \ + for (; _list < _end; _list++) { \ + entry_ptr = _list; + +#define ZEND_TYPE_LIST_FOREACH(list, entry) do { \ + void **_list = (list)->types; \ + void **_end = _list + (list)->num_types; \ + for (; _list < _end; _list++) { \ + entry = *_list; + +#define ZEND_TYPE_LIST_FOREACH_END() \ + } \ +} while (0) + +#define ZEND_TYPE_SET_PTR(t, _ptr) \ + ((t).ptr = (_ptr)) + +#define ZEND_TYPE_SET_PTR_AND_KIND(t, _ptr, kind_bit) do { \ + (t).ptr = (_ptr); \ + (t).type_mask &= ~_ZEND_TYPE_KIND_MASK; \ + (t).type_mask |= (kind_bit); \ +} while (0) + +#define ZEND_TYPE_SET_CE(t, ce) \ + ZEND_TYPE_SET_PTR_AND_KIND(t, ce, _ZEND_TYPE_CE_BIT) + +#define ZEND_TYPE_SET_LIST(t, list) \ + ZEND_TYPE_SET_PTR_AND_KIND(t, list, _ZEND_TYPE_LIST_BIT) + +/* FULL_MASK() includes the MAY_BE_* type mask, the CE/NAME bits, as well as extra reserved bits. + * The PURE_MASK() only includes the MAY_BE_* type mask. */ +#define ZEND_TYPE_FULL_MASK(t) \ + ((t).type_mask) + +#define ZEND_TYPE_PURE_MASK(t) \ + ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK) + +#define ZEND_TYPE_FULL_MASK_WITHOUT_NULL(t) \ + ((t).type_mask & ~_ZEND_TYPE_NULLABLE_BIT) -#define ZEND_TYPE_CODE(t) \ - ((t) >> Z_L(2)) +#define ZEND_TYPE_PURE_MASK_WITHOUT_NULL(t) \ + ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK & ~_ZEND_TYPE_NULLABLE_BIT) + +#define ZEND_TYPE_CONTAINS_CODE(t, code) \ + (((t).type_mask & (1u << (code))) != 0) #define ZEND_TYPE_ALLOW_NULL(t) \ - (((t) & Z_L(0x1)) != 0) + (((t).type_mask & _ZEND_TYPE_NULLABLE_BIT) != 0) + +#define ZEND_TYPE_INIT_NONE(extra_flags) \ + { NULL, (extra_flags) } + +#define ZEND_TYPE_INIT_MASK(_type_mask) \ + { NULL, (_type_mask) } + +#define ZEND_TYPE_INIT_CODE(code, allow_null, extra_flags) \ + ZEND_TYPE_INIT_MASK(((code) == _IS_BOOL ? MAY_BE_BOOL : (1 << (code))) \ + | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags)) -#define ZEND_TYPE_WITHOUT_NULL(t) \ - ((t) & ~Z_L(0x1)) +#define ZEND_TYPE_INIT_PTR(ptr, type_kind, allow_null, extra_flags) \ + { (void *) (ptr), \ + (type_kind) | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } -#define ZEND_TYPE_ENCODE(code, allow_null) \ - (((code) << Z_L(2)) | ((allow_null) ? Z_L(0x1) : Z_L(0x0))) +#define ZEND_TYPE_INIT_PTR_MASK(ptr, type_mask) \ + { (void *) (ptr), (type_mask) } -#define ZEND_TYPE_ENCODE_CE(ce, allow_null) \ - (((uintptr_t)(ce)) | ((allow_null) ? Z_L(0x3) : Z_L(0x2))) +#define ZEND_TYPE_INIT_CE(_ce, allow_null, extra_flags) \ + ZEND_TYPE_INIT_PTR(_ce, _ZEND_TYPE_CE_BIT, allow_null, extra_flags) -#define ZEND_TYPE_ENCODE_CLASS(class_name, allow_null) \ - (((uintptr_t)(class_name)) | ((allow_null) ? Z_L(0x1) : Z_L(0x0))) +#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \ + ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_NAME_BIT, allow_null, extra_flags) -#define ZEND_TYPE_ENCODE_CLASS_CONST_0(class_name) \ - ((zend_type) class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_1(class_name) \ - ((zend_type) "?" class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_Q2(macro, class_name) \ - macro(class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) \ - ZEND_TYPE_ENCODE_CLASS_CONST_Q2(ZEND_TYPE_ENCODE_CLASS_CONST_ ##allow_null, class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST(class_name, allow_null) \ - ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) +#define ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, extra_flags) \ + ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_NAME_BIT, allow_null, extra_flags) + +#define ZEND_TYPE_INIT_CLASS_CONST_MASK(class_name, type_mask) \ + ZEND_TYPE_INIT_PTR_MASK(class_name, _ZEND_TYPE_NAME_BIT | (type_mask)) typedef union _zend_value { zend_long lval; /* long value */ @@ -408,7 +519,7 @@ struct _zend_ast_ref { /*zend_ast ast; zend_ast follows the zend_ast_ref structure */ }; -/* regular data types */ +/* Regular data types: Must be in sync with zend_variables.c. */ #define IS_UNDEF 0 #define IS_NULL 1 #define IS_FALSE 2 @@ -420,22 +531,22 @@ struct _zend_ast_ref { #define IS_OBJECT 8 #define IS_RESOURCE 9 #define IS_REFERENCE 10 +#define IS_CONSTANT_AST 11 /* Constant expressions */ -/* constant expressions */ -#define IS_CONSTANT_AST 11 +/* Fake types used only for type hinting. IS_VOID should be the last. */ +#define IS_CALLABLE 12 +#define IS_ITERABLE 13 +#define IS_VOID 14 /* internal types */ -#define IS_INDIRECT 13 -#define IS_PTR 14 -#define IS_ALIAS_PTR 15 -#define _IS_ERROR 15 - -/* fake types used only for type hinting (Z_TYPE(zv) can not use them) */ -#define _IS_BOOL 16 -#define IS_CALLABLE 17 -#define IS_ITERABLE 18 -#define IS_VOID 19 -#define _IS_NUMBER 20 +#define IS_INDIRECT 15 +#define IS_PTR 16 +#define IS_ALIAS_PTR 17 +#define _IS_ERROR 17 + +/* used for casts */ +#define _IS_BOOL 18 +#define _IS_NUMBER 19 static zend_always_inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; @@ -713,7 +824,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { #define Z_OBJCE(zval) (Z_OBJ(zval)->ce) #define Z_OBJCE_P(zval_p) Z_OBJCE(*(zval_p)) -#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval)) +#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(Z_OBJ(zval)) #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*(zval_p)) #define Z_RES(zval) (zval).value.res @@ -775,17 +886,17 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { (b) ? IS_TRUE : IS_FALSE; \ } while (0) -#define ZVAL_LONG(z, l) { \ +#define ZVAL_LONG(z, l) do { \ zval *__z = (z); \ Z_LVAL_P(__z) = l; \ Z_TYPE_INFO_P(__z) = IS_LONG; \ - } + } while (0) -#define ZVAL_DOUBLE(z, d) { \ +#define ZVAL_DOUBLE(z, d) do { \ zval *__z = (z); \ Z_DVAL_P(__z) = d; \ Z_TYPE_INFO_P(__z) = IS_DOUBLE; \ - } + } while (0) #define ZVAL_STR(z, s) do { \ zval *__z = (z); \ @@ -1266,7 +1377,7 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) { } \ } while (0) -/* Properties store a flag distinguishing unset and unintialized properties +/* Properties store a flag distinguishing unset and uninitialized properties * (both use IS_UNDEF type) in the Z_EXTRA space. As such we also need to copy * the Z_EXTRA space when copying property default values etc. We define separate * macros for this purpose, so this workaround is easier to remove in the future. */ diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index 177c66ed7f..2e012237b3 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index 574bee992b..84a1562c77 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d041d16893..ac70ec003f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -47,7 +47,6 @@ ZEND_VM_HELPER(zend_add_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_HOT_NOCONSTCONST_HANDLER(1, ZEND_ADD, CONST|TMPVARCV, CONST|TMPVARCV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2, *result; double d1, d2; @@ -107,7 +106,6 @@ ZEND_VM_HELPER(zend_sub_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_HOT_NOCONSTCONST_HANDLER(2, ZEND_SUB, CONST|TMPVARCV, CONST|TMPVARCV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2, *result; double d1, d2; @@ -167,7 +165,6 @@ ZEND_VM_HELPER(zend_mul_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_COLD_CONSTCONST_HANDLER(3, ZEND_MUL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2, *result; double d1, d2; @@ -209,7 +206,6 @@ ZEND_VM_C_LABEL(mul_double): ZEND_VM_COLD_CONSTCONST_HANDLER(4, ZEND_DIV, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); @@ -255,7 +251,6 @@ ZEND_VM_HELPER(zend_mod_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_COLD_CONSTCONST_HANDLER(5, ZEND_MOD, CONST|TMPVARCV, CONST|TMPVARCV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2, *result; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -304,7 +299,6 @@ ZEND_VM_HELPER(zend_shift_left_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_COLD_CONSTCONST_HANDLER(6, ZEND_SL, CONST|TMPVARCV, CONST|TMPVARCV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -347,7 +341,6 @@ ZEND_VM_HELPER(zend_shift_right_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVARCV, CONST|TMPVARCV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -367,7 +360,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVARCV, CONST|TMPVARCV) ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); @@ -382,7 +374,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV) ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_CONST)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -454,7 +445,6 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_bool result; @@ -465,14 +455,11 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_bool result; @@ -483,12 +470,11 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CON FREE_OP1(); FREE_OP2(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -498,31 +484,19 @@ ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2) if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret == 0, 1); } ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; @@ -535,13 +509,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { ZEND_VM_C_LABEL(is_equal_true): ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_C_LABEL(is_equal_false): ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -584,6 +554,7 @@ ZEND_VM_C_LABEL(is_equal_double): ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -593,31 +564,19 @@ ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2) if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) != 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret != 0, 1); } ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; @@ -630,13 +589,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TM if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { ZEND_VM_C_LABEL(is_not_equal_true): ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_C_LABEL(is_not_equal_false): ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -679,6 +634,7 @@ ZEND_VM_C_LABEL(is_not_equal_double): ZEND_VM_HELPER(zend_is_smaller_helper, ANY, ANY, zval *op_1, zval *op_2) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -688,31 +644,19 @@ ZEND_VM_HELPER(zend_is_smaller_helper, ANY, ANY, zval *op_1, zval *op_2) if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) < 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret < 0, 1); } ZEND_VM_HOT_NOCONSTCONST_HANDLER(20, ZEND_IS_SMALLER, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; @@ -725,13 +669,9 @@ ZEND_VM_HOT_NOCONSTCONST_HANDLER(20, ZEND_IS_SMALLER, CONST|TMPVARCV, CONST|TMPV if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { ZEND_VM_C_LABEL(is_smaller_true): ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_C_LABEL(is_smaller_false): ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -759,6 +699,7 @@ ZEND_VM_C_LABEL(is_smaller_double): ZEND_VM_HELPER(zend_is_smaller_or_equal_helper, ANY, ANY, zval *op_1, zval *op_2) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -768,31 +709,19 @@ ZEND_VM_HELPER(zend_is_smaller_or_equal_helper, ANY, ANY, zval *op_1, zval *op_2 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) <= 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret <= 0, 1); } ZEND_VM_HOT_NOCONSTCONST_HANDLER(21, ZEND_IS_SMALLER_OR_EQUAL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; @@ -840,7 +769,6 @@ ZEND_VM_C_LABEL(is_smaller_or_equal_double): ZEND_VM_COLD_CONSTCONST_HANDLER(170, ZEND_SPACESHIP, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); @@ -876,7 +804,6 @@ ZEND_VM_HELPER(zend_bw_or_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_COLD_CONSTCONST_HANDLER(9, ZEND_BW_OR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -916,7 +843,6 @@ ZEND_VM_HELPER(zend_bw_and_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_COLD_CONSTCONST_HANDLER(10, ZEND_BW_AND, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -956,7 +882,6 @@ ZEND_VM_HELPER(zend_bw_xor_helper, ANY, ANY, zval *op_1, zval *op_2) ZEND_VM_COLD_CONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -975,7 +900,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVARCV, CONST|TMPVARCV, ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); @@ -990,7 +914,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR ZEND_VM_COLD_CONST_HANDLER(13, ZEND_BW_NOT, CONST|TMPVAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *op1; op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -1012,7 +935,6 @@ ZEND_VM_COLD_CONST_HANDLER(14, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY) { USE_OPLINE zval *val; - zend_free_op free_op1; val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (Z_TYPE_INFO_P(val) == IS_TRUE) { @@ -1063,21 +985,17 @@ ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY) ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - property = GET_OP2_ZVAL_PTR(BP_VAR_R); do { @@ -1092,16 +1010,24 @@ ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } ZEND_VM_C_LABEL(assign_op_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1138,7 +1064,10 @@ ZEND_VM_C_LABEL(assign_op_object): } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1155,7 +1084,6 @@ ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP) /* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */ USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; zend_reference *ref; @@ -1181,7 +1109,7 @@ ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP) prop = Z_REFVAL_P(prop); } - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { /* special case for typed properties */ zend_binary_assign_op_typed_prop(prop_info, prop, value OPLINE_CC EXECUTE_DATA_CC); } else { @@ -1201,7 +1129,6 @@ ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP) ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -1230,7 +1157,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array): } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -1247,7 +1174,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array): if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -1286,7 +1213,6 @@ ZEND_VM_C_LABEL(assign_dim_op_ret_null): ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *var_ptr; zval *value; @@ -1294,26 +1220,20 @@ ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP) value = GET_OP2_ZVAL_PTR(BP_VAR_R); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - var_ptr = Z_REFVAL_P(var_ptr); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } FREE_OP2(); @@ -1324,20 +1244,16 @@ ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP) ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - property = GET_OP2_ZVAL_PTR(BP_VAR_R); do { @@ -1350,16 +1266,24 @@ ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } ZEND_VM_C_LABEL(pre_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1373,7 +1297,10 @@ ZEND_VM_C_LABEL(pre_incdec_object): zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1390,20 +1317,16 @@ ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - property = GET_OP2_ZVAL_PTR(BP_VAR_R); do { @@ -1416,16 +1339,24 @@ ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CAC && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } ZEND_VM_C_LABEL(post_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -1438,7 +1369,10 @@ ZEND_VM_C_LABEL(post_incdec_object): zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1466,7 +1400,8 @@ ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) HANDLE_EXCEPTION(); } - zend_pre_incdec_property_zval(prop, prop_info->type ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -1491,7 +1426,8 @@ ZEND_VM_HANDLER(40, ZEND_POST_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) HANDLE_EXCEPTION(); } - zend_post_incdec_property_zval(prop, prop_info->type ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -1505,18 +1441,10 @@ ZEND_VM_HANDLER(41, ZEND_POST_DEC_STATIC_PROP, ANY, ANY, CACHE_SLOT) ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -1546,7 +1474,6 @@ ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY) ZEND_VM_HOT_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL)) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); @@ -1565,21 +1492,13 @@ ZEND_VM_HOT_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL)) ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } - 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(); } @@ -1607,7 +1526,6 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY) ZEND_VM_HOT_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL)) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); @@ -1626,16 +1544,10 @@ ZEND_VM_HOT_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL)) ZEND_VM_HELPER(zend_post_inc_helper, VAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -1664,7 +1576,6 @@ ZEND_VM_HELPER(zend_post_inc_helper, VAR|CV, ANY) ZEND_VM_HOT_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); @@ -1681,16 +1592,10 @@ ZEND_VM_HOT_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) ZEND_VM_HELPER(zend_post_dec_helper, VAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -1719,7 +1624,6 @@ ZEND_VM_HELPER(zend_post_dec_helper, VAR|CV, ANY) ZEND_VM_HOT_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); @@ -1736,7 +1640,6 @@ ZEND_VM_HOT_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) ZEND_VM_HANDLER(136, ZEND_ECHO, CONST|TMPVAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *z; SAVE_OPLINE(); @@ -1766,7 +1669,6 @@ ZEND_VM_HANDLER(136, ZEND_ECHO, CONST|TMPVAR|CV, ANY) ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type) { USE_OPLINE - zend_free_op free_op1; zval *varname; zval *retval; zend_string *name, *tmp_name; @@ -1808,7 +1710,7 @@ ZEND_VM_C_LABEL(fetch_this): } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -1827,7 +1729,7 @@ ZEND_VM_C_LABEL(fetch_this): } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { ZVAL_NULL(retval); } else { @@ -1915,7 +1817,7 @@ ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, ANY, CLASS_FETCH, CACHE_SLOT) } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, ANY, CLASS_FETCH, FETCH_REF|DIM_OBJ_WRITE|CACHE_SLOT) +ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, ANY, CLASS_FETCH, FETCH_REF|DIM_WRITE|CACHE_SLOT) { ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W); } @@ -1950,7 +1852,6 @@ ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, ANY, CLASS_FETCH, CACHE_SLOT) ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *dim, *value; SAVE_OPLINE(); @@ -1986,7 +1887,6 @@ ZEND_VM_C_LABEL(fetch_dim_r_slow): ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); @@ -1994,8 +1894,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) zend_fetch_dimension_address_W(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2003,7 +1902,6 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); @@ -2011,8 +1909,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) zend_fetch_dimension_address_RW(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2020,7 +1917,6 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) ZEND_VM_COLD_CONSTCONST_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); @@ -2077,7 +1973,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, C ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); @@ -2085,8 +1980,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV) zend_fetch_dimension_address_UNSET(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2094,19 +1988,12 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV) ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1; zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE == IS_CONST || @@ -2133,9 +2020,11 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -2160,10 +2049,10 @@ ZEND_VM_C_LABEL(fetch_obj_r_fast_copy): Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { ZEND_VM_C_GOTO(fetch_obj_r_copy); @@ -2174,7 +2063,7 @@ ZEND_VM_C_LABEL(fetch_obj_r_fast_copy): } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -2186,11 +2075,22 @@ ZEND_VM_C_LABEL(fetch_obj_r_fast_copy): } } } - } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_r_copy): @@ -2206,19 +2106,14 @@ ZEND_VM_C_LABEL(fetch_obj_r_finish): ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_OBJ_WRITE|CACHE_SLOT) +ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - property = GET_OP2_ZVAL_PTR(BP_VAR_R); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -2227,7 +2122,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2235,21 +2130,16 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } property = GET_OP2_ZVAL_PTR(BP_VAR_R); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2257,19 +2147,12 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1; zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - offset = GET_OP2_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE == IS_CONST || @@ -2289,9 +2172,11 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -2316,10 +2201,10 @@ ZEND_VM_C_LABEL(fetch_obj_is_fast_copy): Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { ZEND_VM_C_GOTO(fetch_obj_is_copy); @@ -2330,7 +2215,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_fast_copy): } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -2342,9 +2227,19 @@ ZEND_VM_C_LABEL(fetch_obj_is_fast_copy): } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + 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); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_is_copy): @@ -2380,22 +2275,16 @@ ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THI ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *property, *result; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - property = GET_OP2_ZVAL_PTR(BP_VAR_R); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2403,7 +2292,6 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); @@ -2416,7 +2304,6 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV) ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *dim; SAVE_OPLINE(); @@ -2440,16 +2327,12 @@ ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV) ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV)) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - property = GET_OP2_ZVAL_PTR(BP_VAR_R); value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); @@ -2458,16 +2341,15 @@ ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_ object = Z_REFVAL_P(object); ZEND_VM_C_GOTO(assign_object); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - ZEND_VM_C_GOTO(free_and_exit_assign_obj); - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + ZEND_VM_C_GOTO(free_and_exit_assign_obj); } ZEND_VM_C_LABEL(assign_object): + zobj = Z_OBJ_P(object); if (OP2_TYPE == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -2551,7 +2433,22 @@ ZEND_VM_C_LABEL(fast_assign_obj): ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + FREE_OP_DATA(); + UNDEF_RESULT(); + ZEND_VM_C_GOTO(exit_assign_obj); + } + } + + value = zobj->handlers->write_property(zobj, name, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } ZEND_VM_C_LABEL(free_and_exit_assign_obj): FREE_OP_DATA(); @@ -2569,7 +2466,6 @@ ZEND_VM_C_LABEL(exit_assign_obj): ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV)) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; @@ -2583,7 +2479,7 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA= value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); FREE_OP_DATA(); } else { @@ -2601,9 +2497,7 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA= ZEND_VM_HANDLER(23, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV)) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -2629,11 +2523,12 @@ ZEND_VM_C_LABEL(try_assign_dim_array): Z_ADDREF_P(value); } } else if (OP_DATA_TYPE == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - FREE_OP_DATA(); + zval_ptr_dtor_nogc(free_op_data); } } else if (OP_DATA_TYPE == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -2696,9 +2591,7 @@ ZEND_VM_C_LABEL(try_assign_dim_array): ZEND_VM_C_GOTO(try_assign_dim_array); } } else { - if (OP1_TYPE != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = GET_OP2_ZVAL_PTR(BP_VAR_R); ZEND_VM_C_LABEL(assign_dim_error): FREE_UNFETCHED_OP_DATA(); @@ -2718,7 +2611,6 @@ ZEND_VM_C_LABEL(assign_dim_error): ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *value; zval *variable_ptr; @@ -2726,19 +2618,12 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) value = GET_OP2_ZVAL_PTR(BP_VAR_R); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - FREE_OP2(); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - FREE_OP1_VAR_PTR(); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + FREE_OP1_VAR_PTR(); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2746,7 +2631,6 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *variable_ptr; zval *value_ptr; @@ -2754,15 +2638,11 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (OP1_TYPE == IS_VAR && + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (OP2_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -2786,17 +2666,11 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV)) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - property = GET_OP2_ZVAL_PTR(BP_VAR_R); value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); @@ -2829,7 +2703,6 @@ ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CA ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value_ptr; zend_property_info *prop_info; @@ -2843,13 +2716,11 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); - if (OP_DATA_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - prop = &EG(uninitialized_zval); - } else if (OP_DATA_TYPE == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { + if (OP_DATA_TYPE == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { prop = &EG(uninitialized_zval); } - } else if (UNEXPECTED(prop_info->type)) { + } else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); } else { zend_assign_to_variable_reference(prop, value_ptr); @@ -2989,8 +2860,8 @@ ZEND_VM_HOT_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY) ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -3008,20 +2879,23 @@ ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR) } SAVE_OPLINE(); + op1_type = OP1_TYPE; if (i_zend_is_true(val)) { opline++; } else { opline = OP_JMP_ADDR(opline, opline->op2); } - FREE_OP1(); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -3039,20 +2913,23 @@ ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR) } SAVE_OPLINE(); + op1_type = OP1_TYPE; if (i_zend_is_true(val)) { opline = OP_JMP_ADDR(opline, opline->op2); } else { opline++; } - FREE_OP1(); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -3071,19 +2948,21 @@ ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR) } SAVE_OPLINE(); + op1_type = OP1_TYPE; if (i_zend_is_true(val)) { opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); } else { opline = OP_JMP_ADDR(opline, opline->op2); } - FREE_OP1(); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *val; int ret; @@ -3120,7 +2999,6 @@ ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR) ZEND_VM_COLD_CONST_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *val; int ret; @@ -3167,19 +3045,29 @@ ZEND_VM_HOT_HANDLER(127, ZEND_FE_FREE, TMPVAR, ANY) zval *var; USE_OPLINE - SAVE_OPLINE(); var = EX_VAR(opline->op1.var); - if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) { - zend_hash_iterator_del(Z_FE_ITER_P(var)); + if (Z_TYPE_P(var) != IS_ARRAY) { + SAVE_OPLINE(); + if (Z_FE_ITER_P(var) != (uint32_t)-1) { + zend_hash_iterator_del(Z_FE_ITER_P(var)); + } + zval_ptr_dtor_nogc(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - zval_ptr_dtor_nogc(var); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + + /* This is freeing an array. Use an inlined version of zval_ptr_dtor_nogc. */ + /* PHP only needs to save the opline and check for an exception if the last reference to the array was garbage collected (destructors of elements in the array could throw an exception) */ + if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); } ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -3300,7 +3188,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV, NUM) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var; @@ -3336,7 +3223,6 @@ ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV, NUM) ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV, NUM) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var; @@ -3372,7 +3258,6 @@ ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV, NUM) ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var, *ret; uint32_t i; @@ -3428,7 +3313,6 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM) ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, UNUSED|CLASS_FETCH, CONST|TMPVAR|UNUSED|CV, CACHE_SLOT) { - zend_free_op free_op2; zval *class_name; USE_OPLINE @@ -3474,7 +3358,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -3486,10 +3369,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - if (OP2_TYPE != IS_CONST) { function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); } @@ -3569,7 +3448,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -3600,9 +3478,12 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (OP1_TYPE == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - FREE_OP1(); + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -3661,8 +3542,6 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (OP2_TYPE != IS_UNUSED) { - zend_free_op free_op2; - function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -3698,7 +3577,6 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -3729,13 +3607,9 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_C_GOTO(check_parent_and_self); + HANDLE_EXCEPTION(); } } else { -ZEND_VM_C_LABEL(check_parent_and_self): /* previous opcode is ZEND_FETCH_CLASS */ if (OP1_TYPE == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -3788,7 +3662,6 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT) ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV, NUM) { USE_OPLINE - zend_free_op free_op2; zval *function_name; zend_execute_data *call; @@ -3799,7 +3672,7 @@ ZEND_VM_C_LABEL(try_function_name): if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3843,7 +3716,6 @@ ZEND_VM_C_LABEL(try_function_name): ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) { USE_OPLINE - zend_free_op free_op2; zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; @@ -3855,16 +3727,8 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) SAVE_OPLINE(); function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP2(); - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -3897,14 +3761,10 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); FREE_OP2(); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -3993,6 +3853,10 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) call->prev_execute_data = execute_data; EG(current_execute_data) = call; +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -4000,6 +3864,9 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -4088,15 +3955,9 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - UNDEF_RESULT(); - if (!RETURN_VALUE_USED(opline)) { - ret = &retval; - ZVAL_UNDEF(ret); - } - ZEND_VM_C_GOTO(fcall_by_name_end); - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -4105,6 +3966,9 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -4137,27 +4001,9 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; - zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_abstract_method(fbc); -ZEND_VM_C_LABEL(fcall_except): - UNDEF_RESULT(); - if (!RETURN_VALUE_USED(opline)) { - ret = &retval; - ZVAL_UNDEF(ret); - } - ZEND_VM_C_GOTO(fcall_end); - } else { - zend_deprecated_function(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - ZEND_VM_C_GOTO(fcall_except); - } - } - } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { ret = NULL; @@ -4179,14 +4025,28 @@ ZEND_VM_C_LABEL(fcall_except): ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_deprecated_function(fbc); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!RETURN_VALUE_USED(opline)) { + ret = &retval; + ZVAL_UNDEF(ret); + } + ZEND_VM_C_GOTO(fcall_end); + } + } + call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - ZEND_VM_C_GOTO(fcall_except); - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -4200,6 +4060,9 @@ ZEND_VM_C_LABEL(fcall_except): #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -4214,19 +4077,6 @@ ZEND_VM_C_LABEL(fcall_end): if (!RETURN_VALUE_USED(opline)) { i_zval_ptr_dtor(ret); } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(ret); - } } if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { @@ -4247,16 +4097,15 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV { USE_OPLINE - SAVE_OPLINE(); if (OP1_TYPE == IS_UNUSED) { + SAVE_OPLINE(); zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if !ZEND_VM_SPEC || (OP1_TYPE != IS_UNUSED) zval *retval_ref, *retval_ptr; - zend_free_op free_op1; zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE == IS_CONST) { @@ -4271,26 +4120,35 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) @@ -4298,7 +4156,6 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); return_value = EX(return_value); @@ -4310,9 +4167,9 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) } } else if (!return_value) { if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -4366,7 +4223,6 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC) { USE_OPLINE zval *retval_ptr; - zend_free_op free_op1; SAVE_OPLINE(); @@ -4503,7 +4359,6 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY) { USE_OPLINE zval *retval; - zend_free_op free_op1; zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); @@ -4543,11 +4398,10 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY) ZEND_VM_RETURN(); } -ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) +ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMPVAR|CV, ANY) { USE_OPLINE zval *value; - zend_free_op free_op1; SAVE_OPLINE(); value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -4573,13 +4427,10 @@ ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) } while (0); zend_exception_save(); - if (OP1_TYPE != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - + Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); zend_exception_restore(); - FREE_OP1_IF_VAR(); + FREE_OP1(); HANDLE_EXCEPTION(); } @@ -4640,7 +4491,6 @@ ZEND_VM_HOT_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, NUM) { USE_OPLINE zval *value, *arg; - zend_free_op free_op1; value = GET_OP1_ZVAL_PTR(BP_VAR_R); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -4671,7 +4521,6 @@ ZEND_VM_HOT_SEND_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM, SPEC(QUICK_ARG)) { USE_OPLINE zval *value, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { @@ -4697,7 +4546,6 @@ ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM) { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { @@ -4734,7 +4582,6 @@ ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM) ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, NUM) { USE_OPLINE - zend_free_op free_op1; zval *varptr, *arg; varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -4754,7 +4601,6 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, NUM) ZEND_VM_HOT_SEND_HANDLER(50, ZEND_SEND_VAR_NO_REF_EX, VAR, NUM, SPEC(QUICK_ARG)) { USE_OPLINE - zend_free_op free_op1; zval *varptr, *arg; uint32_t arg_num = opline->op2.num; @@ -4795,19 +4641,12 @@ ZEND_VM_HOT_SEND_HANDLER(50, ZEND_SEND_VAR_NO_REF_EX, VAR, NUM, SPEC(QUICK_ARG)) ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, NUM) { USE_OPLINE - zend_free_op free_op1; zval *varptr, *arg; SAVE_OPLINE(); varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { - ZVAL_NEW_EMPTY_REF(arg); - ZVAL_NULL(Z_REFVAL_P(arg)); - ZEND_VM_NEXT_OPCODE(); - } - if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { @@ -4823,7 +4662,6 @@ ZEND_VM_HOT_SEND_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM, SPEC(QUICK_ARG)) { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { @@ -4890,7 +4728,6 @@ ZEND_VM_HOT_HANDLER(185, ZEND_SEND_FUNC_ARG, VAR, NUM) { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF); @@ -4919,7 +4756,6 @@ ZEND_VM_HOT_HANDLER(185, ZEND_SEND_FUNC_ARG, VAR, NUM) ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY) { USE_OPLINE - zend_free_op free_op1; zval *args; int arg_num; @@ -4985,7 +4821,7 @@ ZEND_VM_C_LABEL(send_again): zend_object_iterator *iter; if (!ce || !ce->get_iterator) { - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } else { iter = ce->get_iterator(ce, args, 0); @@ -5062,7 +4898,7 @@ ZEND_VM_C_LABEL(send_again): if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } FREE_OP1(); @@ -5072,7 +4908,6 @@ ZEND_VM_C_LABEL(send_again): ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM) { USE_OPLINE - zend_free_op free_op1; zval *args; SAVE_OPLINE(); @@ -5085,16 +4920,10 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM) ZEND_VM_C_GOTO(send_array); } } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); - if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { - OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); - } else if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_RELEASE_THIS) { - OBJ_RELEASE(Z_OBJ(EX(call)->This)); - } - EX(call)->func = (zend_function*)&zend_pass_function; - Z_OBJ(EX(call)->This) = NULL; - ZEND_CALL_INFO(EX(call)) &= ~(ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS); + zend_type_error("call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); FREE_UNFETCHED_OP2(); + FREE_OP1(); + HANDLE_EXCEPTION(); } else { uint32_t arg_num; HashTable *ht; @@ -5104,7 +4933,6 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM) ZEND_VM_C_LABEL(send_array): ht = Z_ARRVAL_P(args); if (OP2_TYPE != IS_UNUSED) { - zend_free_op free_op2; zval *op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); uint32_t skip = opline->extended_value; uint32_t count = zend_hash_num_elements(ht); @@ -5183,7 +5011,6 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|VAR|CV, NUM) { USE_OPLINE zval *arg, *param; - zend_free_op free_op1; SAVE_OPLINE(); @@ -5198,7 +5025,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|VAR|CV, NUM) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED|CACHE_SLOT) +ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -5211,7 +5038,7 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED|CACHE_SLOT) zval *param = EX_VAR(opline->result.var); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -5257,10 +5084,8 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT) } else { ZEND_VM_C_LABEL(recv_init_check_type): if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zval *default_value = RT_CONSTANT(opline, opline->op2); - SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -5270,7 +5095,7 @@ ZEND_VM_C_LABEL(recv_init_check_type): ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED|CACHE_SLOT) +ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -5290,7 +5115,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED|CACHE_SLOT) param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_variadic_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)); + zend_verify_variadic_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)); if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); ZEND_HASH_FILL_ADD(param); param++; @@ -5314,7 +5139,6 @@ ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY) { USE_OPLINE zval *val; - zend_free_op free_op1; val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (Z_TYPE_INFO_P(val) == IS_TRUE) { @@ -5339,6 +5163,7 @@ ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY) ZEND_VM_HELPER(zend_case_helper, ANY, ANY, zval *op_1, zval *op_2) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -5348,28 +5173,16 @@ ZEND_VM_HELPER(zend_case_helper, ANY, ANY, zval *op_1, zval *op_2) if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret == 0, 1); } ZEND_VM_HANDLER(48, ZEND_CASE, TMPVAR, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; @@ -5380,13 +5193,9 @@ ZEND_VM_HANDLER(48, ZEND_CASE, TMPVAR, CONST|TMPVAR|CV) if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { ZEND_VM_C_LABEL(case_true): ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_C_LABEL(case_false): ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -5496,8 +5305,8 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -5505,10 +5314,6 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) SAVE_OPLINE(); obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - do { if (OP1_TYPE == IS_CONST || (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { @@ -5531,9 +5336,10 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); FREE_OP1(); @@ -5554,7 +5360,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -5650,7 +5456,6 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, REF) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -5689,7 +5494,6 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE } if (OP2_TYPE != IS_UNUSED) { - zend_free_op free_op2; zval *offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); zend_string *str; zend_ulong hval; @@ -5748,12 +5552,11 @@ ZEND_VM_C_LABEL(num_index): ZEND_VM_HANDLER(147, ZEND_ADD_ARRAY_UNPACK, ANY, ANY) { USE_OPLINE - zend_free_op free_op1; 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); @@ -5782,7 +5585,7 @@ ZEND_VM_C_LABEL(add_unpack_again): zend_object_iterator *iter; if (!ce || !ce->get_iterator) { - zend_throw_error(NULL, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } else { iter = ce->get_iterator(ce, op1, 0); if (UNEXPECTED(!iter)) { @@ -5794,11 +5597,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; @@ -5847,7 +5650,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(); } @@ -5876,7 +5679,6 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSE ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE) { USE_OPLINE - zend_free_op free_op1; zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; @@ -5972,7 +5774,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL) { USE_OPLINE zend_op_array *new_op_array; - zend_free_op free_op1; zval *inc_filename; SAVE_OPLINE(); @@ -6062,7 +5863,6 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; - zend_free_op free_op1; SAVE_OPLINE(); @@ -6101,7 +5901,6 @@ ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT) zval *varname; zend_string *name, *tmp_name = NULL; zend_class_entry *ce; - zend_free_op free_op1; SAVE_OPLINE(); @@ -6136,7 +5935,11 @@ ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT) if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { varname = ZVAL_UNDEFINED_OP1(); } - name = zval_get_tmp_string(varname, &tmp_name); + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + FREE_OP1(); + HANDLE_EXCEPTION(); + } } zend_std_unset_static_property(ce, name); @@ -6149,7 +5952,6 @@ ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT) ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|CV, CONST|TMPVAR|CV) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; zval *offset; zend_ulong hval; @@ -6207,7 +6009,7 @@ ZEND_VM_C_LABEL(num_index_dim): key = ZSTR_EMPTY_ALLOC(); ZEND_VM_C_GOTO(str_index_dim); } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -6226,7 +6028,7 @@ ZEND_VM_C_LABEL(num_index_dim): if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -6240,15 +6042,12 @@ ZEND_VM_C_LABEL(num_index_dim): ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET); - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } offset = GET_OP2_ZVAL_PTR(BP_VAR_R); do { @@ -6266,7 +6065,18 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); FREE_OP2(); @@ -6277,7 +6087,6 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *result; SAVE_OPLINE(); @@ -6294,20 +6103,27 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE(); } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (OP1_TYPE != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -6335,7 +6151,6 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *array_ref; SAVE_OPLINE(); @@ -6768,25 +6583,15 @@ ZEND_VM_HOT_HANDLER(154, ZEND_ISSET_ISEMPTY_CV, CV, UNUSED, ISSET, SPEC(ISSET)) if (Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else { int result; SAVE_OPLINE(); result = !i_zend_is_true(value); - if (UNEXPECTED(EG(exception))) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH(result, 1); } } @@ -6795,7 +6600,6 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH| USE_OPLINE zval *value; int result; - zend_free_op free_op1; zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; @@ -6833,8 +6637,6 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH| } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ @@ -6856,14 +6658,11 @@ ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, ANY, CLASS_FETCH, ISSET|CAC } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_COLD_CONSTCONST_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|CV, CONST|TMPVAR|CV, ISSET) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; int result; zend_ulong hval; @@ -6898,6 +6697,10 @@ ZEND_VM_C_LABEL(num_index_prop): ZEND_VM_C_GOTO(isset_again); } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + ZEND_VM_C_GOTO(isset_dim_obj_exit); + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -6909,8 +6712,6 @@ ZEND_VM_C_LABEL(num_index_prop): /* avoid exception check */ FREE_OP2(); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -6936,25 +6737,18 @@ ZEND_VM_C_LABEL(isset_dim_obj_exit): FREE_OP2(); FREE_OP1(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, ISSET|CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS); - - if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper); - } - offset = GET_OP2_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE == IS_CONST || @@ -6971,26 +6765,37 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED } } + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + ZEND_VM_C_GOTO(isset_object_finish); + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } ZEND_VM_C_LABEL(isset_object_finish): FREE_OP2(); FREE_OP1(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_HANDLER(194, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -7008,14 +6813,13 @@ ZEND_VM_C_LABEL(array_key_exists_array): ZEND_VM_C_GOTO(array_key_exists_array); } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } FREE_OP2(); FREE_OP1(); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -7025,7 +6829,6 @@ ZEND_VM_COLD_HANDLER(79, ZEND_EXIT, ANY, ANY) SAVE_OPLINE(); if (OP1_TYPE != IS_UNUSED) { - zend_free_op free_op1; zval *ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); do { @@ -7054,9 +6857,10 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EG(error_reporting)) { + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { do { - EG(error_reporting) = 0; + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; if (!EG(error_reporting_ini_entry)) { zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1); if (zv) { @@ -7085,7 +6889,8 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) { USE_OPLINE - if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); @@ -7094,7 +6899,6 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; int ret; @@ -7144,7 +6948,6 @@ ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR) ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; @@ -7184,7 +6987,6 @@ ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR) ZEND_VM_HOT_HANDLER(31, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *result = EX_VAR(opline->result.var); @@ -7351,7 +7153,6 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM) ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1; zval *expr; zend_bool result; @@ -7393,8 +7194,6 @@ ZEND_VM_C_LABEL(try_instanceof): } FREE_OP1(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_HOT_HANDLER(104, ZEND_EXT_NOP, ANY, ANY) @@ -7519,7 +7318,10 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) break; /* return value is zend_class_entry pointer */ default: - zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var)); + /* smart branch opcodes may not initialize result */ + if (!zend_is_smart_branch(throw_op)) { + zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var)); + } } } @@ -7560,7 +7362,6 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY) ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *name; zval *val; zend_constant c; @@ -7652,7 +7453,7 @@ ZEND_VM_COLD_HELPER(zend_yield_in_closed_generator_helper, ANY, ANY) HANDLE_EXCEPTION(); } -ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSED, SRC) +ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED, SRC) { USE_OPLINE @@ -7671,8 +7472,6 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE /* Set the new yielded value */ if (OP1_TYPE != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -7741,26 +7540,12 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE /* Set the new yielded key */ if (OP2_TYPE != IS_UNUSED) { - zend_free_op free_op2; zval *key = GET_OP2_ZVAL_PTR(BP_VAR_R); - - /* Consts, temporary variables and references need copying */ - if (OP2_TYPE == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (OP2_TYPE == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - FREE_OP2_IF_VAR(); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (OP2_TYPE == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((OP2_TYPE & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + FREE_OP2(); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -7793,17 +7578,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE ZEND_VM_RETURN(); } -ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY) +ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMPVAR|CV, ANY) { USE_OPLINE - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - zval *val; - zend_free_op free_op1; SAVE_OPLINE(); - val = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); + val = GET_OP1_ZVAL_PTR(BP_VAR_R); if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); @@ -7812,23 +7594,21 @@ ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY) HANDLE_EXCEPTION(); } +ZEND_VM_C_LABEL(yield_from_try_again): if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); - if (OP1_TYPE != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { + if (Z_OPT_REFCOUNTED_P(val)) { Z_ADDREF_P(val); } Z_FE_POS(generator->values) = 0; - - FREE_OP1_IF_VAR(); + FREE_OP1(); } else if (OP1_TYPE != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { zend_class_entry *ce = Z_OBJCE_P(val); if (ce == zend_ce_generator) { zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - if (OP1_TYPE != IS_TMP_VAR) { - Z_ADDREF_P(val); - } - FREE_OP1_IF_VAR(); + Z_ADDREF_P(val); + FREE_OP1(); if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { @@ -7874,6 +7654,9 @@ ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY) ZVAL_OBJ(&generator->values, &iter->std); } + } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + ZEND_VM_C_GOTO(yield_from_try_again); } else { zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); UNDEF_RESULT(); @@ -7958,7 +7741,6 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH) ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT) { USE_OPLINE - zend_free_op free_op1, free_op2; zend_string *varname; zval *value; zval *variable_ptr; @@ -8042,7 +7824,6 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY) { USE_OPLINE zval *value; - zend_free_op free_op1; value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { @@ -8080,9 +7861,9 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY) zval_ptr_dtor(&tmp); } if (!EG(exception)) { - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } FREE_OP1(); @@ -8094,12 +7875,11 @@ ZEND_VM_HOT_NOCONST_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMPVAR|CV, ANY, TYPE_MAS USE_OPLINE zval *value; int result = 0; - zend_free_op free_op1; value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { ZEND_VM_C_LABEL(type_check_resource): - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -8121,12 +7901,8 @@ ZEND_VM_C_LABEL(type_check_resource): SAVE_OPLINE(); FREE_OP1(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } @@ -8140,13 +7916,9 @@ ZEND_VM_HOT_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT) if (!IS_SPECIAL_CACHE_VAL(c)) { ZEND_VM_C_LABEL(defined_true): ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) { ZEND_VM_C_LABEL(defined_false): ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { @@ -8281,14 +8053,9 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - zend_vm_stack_free_call_frame(call); - if (ret) { - ZVAL_UNDEF(ret); - } - ZEND_VM_C_GOTO(call_trampoline_end); - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif if (ret == NULL) { ZVAL_NULL(&retval); @@ -8304,6 +8071,9 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -8313,7 +8083,6 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) EG(current_execute_data) = call->prev_execute_data; -ZEND_VM_C_LABEL(call_trampoline_end): zend_vm_stack_free_args(call); if (ret == &retval) { zval_ptr_dtor(ret); @@ -8345,7 +8114,6 @@ ZEND_VM_C_LABEL(call_trampoline_end): ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *closure, *var; closure = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -8378,7 +8146,6 @@ ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF) ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF) { USE_OPLINE - zend_free_op free_op1; HashTable *ht; zval *value; zval *variable_ptr; @@ -8429,7 +8196,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED) +ZEND_VM_HOT_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED) { USE_OPLINE @@ -8503,7 +8270,6 @@ ZEND_VM_HANDLER(140, ZEND_MAKE_REF, VAR|CV, UNUSED) ZEND_VM_COLD_CONSTCONST_HANDLER(187, ZEND_SWITCH_LONG, CONST|TMPVARCV, CONST, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op, *jump_zv; HashTable *jumptable; @@ -8532,7 +8298,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(187, ZEND_SWITCH_LONG, CONST|TMPVARCV, CONST, JM ZEND_VM_COLD_CONSTCONST_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVARCV, CONST, JMP_ADDR) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op, *jump_zv; HashTable *jumptable; @@ -8566,7 +8331,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVARCV, CONST, ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM) { USE_OPLINE - zend_free_op free_op1; zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; @@ -8585,13 +8349,12 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } @@ -8599,14 +8362,11 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM } FREE_OP1(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_long count; @@ -8617,9 +8377,11 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED) count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } if (UNEXPECTED(EG(exception))) { @@ -8629,10 +8391,10 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED) } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -8675,7 +8437,6 @@ ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMPVAR|CV, UNUSED) ZEND_VM_NEXT_OPCODE(); } } else { - zend_free_op free_op1; zval *op1; SAVE_OPLINE(); @@ -8690,8 +8451,8 @@ ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMPVAR|CV, UNUSED) if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } @@ -8722,7 +8483,6 @@ ZEND_VM_HANDLER(192, ZEND_GET_CALLED_CLASS, UNUSED, UNUSED) ZEND_VM_COLD_CONST_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_string *type; @@ -8824,7 +8584,6 @@ ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED) ZEND_VM_HANDLER(167, ZEND_COPY_TMP, TMPVAR, UNUSED) { USE_OPLINE - zend_free_op free_op1; zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R); zval *result = EX_VAR(opline->result.var); ZVAL_COPY(result, value); @@ -8949,7 +8708,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info = ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) +ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL|ZEND_IS_IDENTICAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) { USE_OPLINE zval *op1, *op2; @@ -8959,11 +8718,9 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_inf op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) +ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL|ZEND_IS_IDENTICAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) { USE_OPLINE zval *op1, *op2; @@ -8973,11 +8730,9 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_i op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) +ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) { USE_OPLINE zval *op1, *op2; @@ -8987,11 +8742,9 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) +ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE)) { USE_OPLINE zval *op1, *op2; @@ -9001,8 +8754,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && o op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST)) @@ -9015,8 +8766,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_i op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST)) @@ -9029,8 +8778,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_OR_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST)) @@ -9043,8 +8790,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_OR_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST)) @@ -9057,8 +8802,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUB op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG_NO_OVERFLOW, CV, ANY, SPEC(RETVAL)) @@ -9160,7 +8903,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POS ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_LONG), ZEND_QM_ASSIGN_LONG, CONST|TMPVARCV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *value; value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -9171,7 +8913,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_LONG), ZEND_QM ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_ASSIGN_DOUBLE, CONST|TMPVARCV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *value; value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -9182,7 +8923,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY) { USE_OPLINE - zend_free_op free_op1; zval *value; value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -9193,7 +8933,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, ((op->op1_type == IS_CONST) ? !Z_R ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVARCV, SPEC(NO_CONST_CONST)) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *dim, *value; zend_long offset; HashTable *ht; @@ -9247,7 +8986,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_RE { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -9265,7 +9003,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, op->op2.num <= MAX_ARG_FLAG_NUM { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { @@ -9288,7 +9025,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAL, op->op1_type == IS_CONST && !Z_REFC { USE_OPLINE zval *value, *arg; - zend_free_op free_op1; value = GET_OP1_ZVAL_PTR(BP_VAR_R); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -9300,7 +9036,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAL_EX, op->op2.num <= MAX_ARG_FLAG_NUM { USE_OPLINE zval *value, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b015558084..859f8bf9d7 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -578,6 +578,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -587,29 +588,19 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_hel if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret == 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -619,29 +610,19 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) != 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret != 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -651,29 +632,19 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_h if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) < 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret < 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_or_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -683,25 +654,14 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_o if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) <= 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret <= 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_or_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) @@ -797,7 +757,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN /* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */ USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; zend_reference *ref; @@ -811,7 +770,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN HANDLE_EXCEPTION(); } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (UNEXPECTED(Z_ISREF_P(prop))) { @@ -823,7 +782,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN prop = Z_REFVAL_P(prop); } - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { /* special case for typed properties */ zend_binary_assign_op_typed_prop(prop_info, prop, value OPLINE_CC EXECUTE_DATA_CC); } else { @@ -835,7 +794,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN ZVAL_COPY(EX_VAR(opline->result.var), prop); } - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_static_prop has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -853,7 +812,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_STATIC_PROP_SPEC_HANDL HANDLE_EXCEPTION(); } - zend_pre_incdec_property_zval(prop, prop_info->type ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -872,7 +832,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_STATIC_PROP_SPEC_HAND HANDLE_EXCEPTION(); } - zend_post_incdec_property_zval(prop, prop_info->type ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -964,7 +925,6 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_us static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *prop, *value; zend_property_info *prop_info; @@ -978,7 +938,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); } else { @@ -996,7 +956,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; @@ -1008,11 +967,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT HANDLE_EXCEPTION(); } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { value = zend_assign_to_variable(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } @@ -1028,7 +987,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; @@ -1040,11 +998,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT HANDLE_EXCEPTION(); } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { value = zend_assign_to_variable(prop, value, IS_VAR, EX_USES_STRICT_TYPES()); } @@ -1060,7 +1018,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *prop, *value; zend_property_info *prop_info; @@ -1074,7 +1031,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); } else { @@ -1092,7 +1049,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value_ptr; zend_property_info *prop_info; @@ -1104,15 +1060,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA HANDLE_EXCEPTION(); } - value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, &free_op_data, BP_VAR_W); + value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, BP_VAR_W); - if ((opline+1)->op1_type == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - prop = &EG(uninitialized_zval); - } else if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { + if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { prop = &EG(uninitialized_zval); } - } else if (UNEXPECTED(prop_info->type)) { + } else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); } else { zend_assign_to_variable_reference(prop, value_ptr); @@ -1122,7 +1076,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA ZVAL_COPY(EX_VAR(opline->result.var), prop); } - if (free_op_data) {zval_ptr_dtor_nogc(free_op_data);}; + if ((opline+1)->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));}; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -1263,6 +1217,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV call->prev_execute_data = execute_data; EG(current_execute_data) = call; +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1270,6 +1228,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1308,6 +1269,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV call->prev_execute_data = execute_data; EG(current_execute_data) = call; +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1315,6 +1280,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1426,15 +1394,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - UNDEF_RESULT(); - if (!0) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_by_name_end; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1443,6 +1405,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1510,15 +1475,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - UNDEF_RESULT(); - if (!1) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_by_name_end; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1527,6 +1486,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1559,27 +1521,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; - zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_abstract_method(fbc); -fcall_except: - UNDEF_RESULT(); - if (!0) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_end; - } else { - zend_deprecated_function(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - goto fcall_except; - } - } - } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { ret = NULL; @@ -1601,14 +1545,28 @@ fcall_except: ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_deprecated_function(fbc); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!0) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - goto fcall_except; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1622,6 +1580,9 @@ fcall_except: #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1636,19 +1597,6 @@ fcall_end: if (!0) { i_zval_ptr_dtor(ret); } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ret = 0 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!0) { - zval_ptr_dtor(ret); - } } if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { @@ -1671,27 +1619,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; - zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_abstract_method(fbc); -fcall_except: - UNDEF_RESULT(); - if (!1) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_end; - } else { - zend_deprecated_function(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - goto fcall_except; - } - } - } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { ret = NULL; @@ -1713,14 +1643,28 @@ fcall_except: ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_deprecated_function(fbc); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!1) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - goto fcall_except; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1734,6 +1678,9 @@ fcall_except: #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1748,19 +1695,6 @@ fcall_end: if (!1) { i_zval_ptr_dtor(ret); } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ret = 1 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!1) { - zval_ptr_dtor(ret); - } } if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { @@ -1870,12 +1804,11 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_ca static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *args; int arg_num; SAVE_OPLINE(); - args = get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + args = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1; send_again: @@ -1906,7 +1839,7 @@ send_again: ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { if (name) { zend_throw_error(NULL, "Cannot unpack array with string keys"); - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); HANDLE_EXCEPTION(); } @@ -1936,12 +1869,12 @@ send_again: zend_object_iterator *iter; if (!ce || !ce->get_iterator) { - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } else { iter = ce->get_iterator(ce, args, 0); if (UNEXPECTED(!iter)) { - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); if (!EG(exception)) { zend_throw_exception_ex( NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name) @@ -2013,21 +1946,20 @@ send_again: if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *args; SAVE_OPLINE(); - args = get_zval_ptr(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + args = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) { if ((opline->op1_type & (IS_VAR|IS_CV)) && Z_ISREF_P(args)) { @@ -2036,16 +1968,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O goto send_array; } } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); - if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { - OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); - } else if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_RELEASE_THIS) { - OBJ_RELEASE(Z_OBJ(EX(call)->This)); - } - EX(call)->func = (zend_function*)&zend_pass_function; - Z_OBJ(EX(call)->This) = NULL; - ZEND_CALL_INFO(EX(call)) &= ~(ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS); + zend_type_error("call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); } else { uint32_t arg_num; HashTable *ht; @@ -2055,8 +1981,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O send_array: ht = Z_ARRVAL_P(args); if (opline->op2_type != IS_UNUSED) { - zend_free_op free_op2; - zval *op2 = get_zval_ptr(opline->op2_type, opline->op2, &free_op2, BP_VAR_R); + zval *op2 = get_zval_ptr(opline->op2_type, opline->op2, BP_VAR_R); uint32_t skip = opline->extended_value; uint32_t count = zend_hash_num_elements(ht); zend_long len = zval_get_long(op2); @@ -2098,7 +2023,7 @@ send_array: param++; } ZEND_HASH_FOREACH_END(); } - FREE_OP(free_op2); + FREE_OP(opline->op2_type, opline->op2.var); } else { zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht)); arg_num = 1; @@ -2126,12 +2051,13 @@ send_array: } ZEND_HASH_FOREACH_END(); } } - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -2141,32 +2067,20 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_ if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret == 0, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; SAVE_OPLINE(); - op1 = get_zval_ptr(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + op1 = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); add_unpack_again: if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) { @@ -2177,7 +2091,7 @@ add_unpack_again: ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { if (key) { zend_throw_error(NULL, "Cannot unpack array with string keys"); - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); HANDLE_EXCEPTION(); } else { if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) { @@ -2196,11 +2110,11 @@ add_unpack_again: zend_object_iterator *iter; if (!ce || !ce->get_iterator) { - zend_throw_error(NULL, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } else { iter = ce->get_iterator(ce, op1, 0); if (UNEXPECTED(!iter)) { - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); if (!EG(exception)) { zend_throw_exception_ex( NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name) @@ -2262,7 +2176,7 @@ add_unpack_again: zend_throw_error(NULL, "Only arrays and Traversables can be unpacked"); } - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2272,7 +2186,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP zval *varname; zend_string *name, *tmp_name = NULL; zend_class_entry *ce; - zend_free_op free_op1; SAVE_OPLINE(); @@ -2298,7 +2211,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP ce = Z_CE_P(EX_VAR(opline->op2.var)); } - varname = get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + varname = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); if (opline->op1_type == IS_CONST) { name = Z_STR_P(varname); } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { @@ -2307,13 +2220,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { varname = ZVAL_UNDEFINED_OP1(); } - name = zval_get_tmp_string(varname, &tmp_name); + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } } zend_std_unset_static_property(ce, name); zend_tmp_string_release(tmp_name); - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2335,8 +2252,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -2345,8 +2260,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER SAVE_OPLINE(); if (opline->op1_type != IS_UNUSED) { - zend_free_op free_op1; - zval *ptr = get_zval_ptr(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + zval *ptr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); do { if (Z_TYPE_P(ptr) == IS_LONG) { @@ -2362,7 +2276,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER zend_print_zval(ptr, 0); } } while (0); - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); } zend_bailout(); ZEND_VM_NEXT_OPCODE(); /* Never reached */ @@ -2374,9 +2288,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EG(error_reporting)) { + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { do { - EG(error_reporting) = 0; + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; if (!EG(error_reporting_ini_entry)) { zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1); if (zv) { @@ -2612,7 +2527,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( break; /* return value is zend_class_entry pointer */ default: - zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var)); + /* smart branch opcodes may not initialize result */ + if (!zend_is_smart_branch(throw_op)) { + zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var)); + } } } @@ -2796,14 +2714,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - zend_vm_stack_free_call_frame(call); - if (ret) { - ZVAL_UNDEF(ret); - } - goto call_trampoline_end; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif if (ret == NULL) { ZVAL_NULL(&retval); @@ -2819,6 +2732,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -2828,7 +2744,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z EG(current_execute_data) = call->prev_execute_data; -call_trampoline_end: zend_vm_stack_free_args(call); if (ret == &retval) { zval_ptr_dtor(ret); @@ -2908,7 +2823,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_execute_data *call; @@ -2919,7 +2833,7 @@ try_function_name: if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3061,10 +2975,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON } else { recv_init_check_type: if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zval *default_value = RT_CONSTANT(opline, opline->op2); - SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -3077,18 +2989,17 @@ recv_init_check_type: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *function_name; zend_execute_data *call; SAVE_OPLINE(); - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); try_function_name: if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3105,7 +3016,7 @@ try_function_name: call = NULL; } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (UNEXPECTED(!call)) { HANDLE_EXCEPTION(); } @@ -3142,7 +3053,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H zval *param = EX_VAR(opline->result.var); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -3170,7 +3081,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_variadic_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)); + zend_verify_variadic_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)); if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); ZEND_HASH_FILL_ADD(param); param++; @@ -3193,7 +3104,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_execute_data *call; @@ -3204,7 +3114,7 @@ try_function_name: if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3247,7 +3157,6 @@ try_function_name: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; op1 = RT_CONSTANT(opline, opline->op1); @@ -3270,7 +3179,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CON USE_OPLINE zval *val; - val = RT_CONSTANT(opline, opline->op1); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -3295,7 +3203,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *z; SAVE_OPLINE(); @@ -3324,8 +3231,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_O static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = RT_CONSTANT(opline, opline->op1); @@ -3343,20 +3250,23 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_H } SAVE_OPLINE(); + op1_type = IS_CONST; if (i_zend_is_true(val)) { opline++; } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = RT_CONSTANT(opline, opline->op1); @@ -3374,20 +3284,23 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_ } SAVE_OPLINE(); + op1_type = IS_CONST; if (i_zend_is_true(val)) { opline = OP_JMP_ADDR(opline, opline->op2); } else { opline++; } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = RT_CONSTANT(opline, opline->op1); @@ -3406,19 +3319,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND } SAVE_OPLINE(); + op1_type = IS_CONST; if (i_zend_is_true(val)) { opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; int ret; @@ -3455,7 +3370,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONS static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; int ret; @@ -3493,7 +3407,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); @@ -3505,9 +3418,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } } else if (!return_value) { if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -3562,7 +3475,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE USE_OPLINE zval *retval_ptr; - SAVE_OPLINE(); do { @@ -3622,7 +3534,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HA USE_OPLINE zval *retval; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); @@ -3666,7 +3577,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_ USE_OPLINE zval *value; - SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op1); @@ -3691,10 +3601,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_ } while (0); zend_exception_save(); - if (IS_CONST != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - + Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); zend_exception_restore(); @@ -3759,7 +3666,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONS USE_OPLINE zval *value, *arg; - value = RT_CONSTANT(opline, opline->op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, value); @@ -3775,7 +3681,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER { USE_OPLINE zval *value, *arg; - uint32_t arg_num = opline->op2.num; if (EXPECTED(0)) { @@ -3801,7 +3706,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_C { USE_OPLINE zval *value, *arg; - uint32_t arg_num = opline->op2.num; if (EXPECTED(1)) { @@ -3828,7 +3732,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CONST_HANDLER(Z USE_OPLINE zval *arg, *param; - SAVE_OPLINE(); if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { @@ -3847,7 +3750,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_H USE_OPLINE zval *val; - val = RT_CONSTANT(opline, opline->op1); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -3872,8 +3774,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_H static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -3881,10 +3783,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ SAVE_OPLINE(); obj = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - do { if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { @@ -3907,9 +3805,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -3930,7 +3829,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -3938,7 +3837,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; @@ -4032,7 +3930,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN { USE_OPLINE zend_op_array *new_op_array; - zval *inc_filename; SAVE_OPLINE(); @@ -4097,7 +3994,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *result; SAVE_OPLINE(); @@ -4113,20 +4009,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_CONST != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -4152,7 +4055,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; SAVE_OPLINE(); @@ -4245,7 +4147,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; int ret; @@ -4294,7 +4195,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONS static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; @@ -4333,7 +4233,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CON static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *result = EX_VAR(opline->result.var); @@ -4381,12 +4280,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - zval *val; - SAVE_OPLINE(); val = RT_CONSTANT(opline, opline->op1); @@ -4397,9 +4293,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( HANDLE_EXCEPTION(); } +yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); - if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { + if (Z_OPT_REFCOUNTED_P(val)) { Z_ADDREF_P(val); } Z_FE_POS(generator->values) = 0; @@ -4409,9 +4306,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( if (ce == zend_ce_generator) { zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - if (IS_CONST != IS_TMP_VAR) { - Z_ADDREF_P(val); - } + Z_ADDREF_P(val); if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { @@ -4456,6 +4351,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( ZVAL_OBJ(&generator->values, &iter->std); } + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; } else { zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); UNDEF_RESULT(); @@ -4487,7 +4385,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST USE_OPLINE zval *value; - value = RT_CONSTANT(opline, opline->op1); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); @@ -4524,9 +4421,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST zval_ptr_dtor(&tmp); } if (!EG(exception)) { - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -4539,11 +4436,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_C zval *value; int result = 0; - value = RT_CONSTANT(opline, opline->op1); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -4565,12 +4461,8 @@ type_check_resource: SAVE_OPLINE(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } @@ -4584,13 +4476,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST if (!IS_SPECIAL_CACHE_VAL(c)) { defined_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) { defined_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { @@ -4604,7 +4492,6 @@ defined_false: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = RT_CONSTANT(opline, opline->op1); @@ -4615,7 +4502,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = RT_CONSTANT(opline, opline->op1); @@ -4626,7 +4512,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_S static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = RT_CONSTANT(opline, opline->op1); @@ -4639,7 +4524,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SIMPLE_SP USE_OPLINE zval *value, *arg; - value = RT_CONSTANT(opline, opline->op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, value); @@ -4650,7 +4534,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE { USE_OPLINE zval *value, *arg; - uint32_t arg_num = opline->op2.num; if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { @@ -4665,7 +4548,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -4704,7 +4586,6 @@ add_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -4743,7 +4624,6 @@ sub_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -4785,7 +4665,6 @@ mul_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -4800,7 +4679,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = RT_CONSTANT(opline, opline->op1); @@ -4828,7 +4706,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -4850,7 +4727,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CON static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -4870,7 +4746,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CON static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -4885,7 +4760,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -4896,14 +4770,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } 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; zend_bool result; @@ -4914,14 +4785,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -4934,13 +4802,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CON if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -4984,7 +4848,6 @@ is_equal_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -4997,13 +4860,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -5047,7 +4906,6 @@ is_not_equal_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -5060,13 +4918,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_C if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -5095,7 +4949,6 @@ is_smaller_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -5143,7 +4996,6 @@ is_smaller_or_equal_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -5158,7 +5010,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -5177,7 +5028,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -5196,7 +5046,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -5215,7 +5064,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -5230,7 +5078,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CON static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -5266,7 +5113,6 @@ fetch_dim_r_slow: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -5299,19 +5145,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_AR static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST || @@ -5338,9 +5177,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5365,10 +5206,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -5379,7 +5220,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5391,11 +5232,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -5414,19 +5266,12 @@ fetch_obj_r_finish: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST || @@ -5446,9 +5291,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5473,10 +5320,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -5487,7 +5334,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5499,9 +5346,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -5537,7 +5394,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -5550,7 +5406,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -5672,7 +5527,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -5684,10 +5538,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); } @@ -5767,7 +5617,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -5797,9 +5646,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -5858,8 +5710,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { - - function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -5895,7 +5745,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -5926,13 +5775,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -5957,7 +5802,6 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; @@ -5969,16 +5813,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS SAVE_OPLINE(); function_name = RT_CONSTANT(opline, opline->op2); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -6010,14 +5846,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -6102,7 +5934,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -6141,7 +5972,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -6221,7 +6051,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HA static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zend_ulong hval; @@ -6256,6 +6085,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -6267,8 +6100,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -6294,25 +6125,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST || @@ -6329,26 +6153,37 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -6366,13 +6201,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -6409,7 +6243,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *name; zval *val; zend_constant c; @@ -6457,8 +6290,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -6526,26 +6357,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -6581,7 +6397,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; @@ -6610,7 +6425,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; @@ -6644,7 +6458,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPE static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; @@ -6663,13 +6476,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } @@ -6677,14 +6489,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -6723,7 +6532,6 @@ add_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -6762,7 +6570,6 @@ sub_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = RT_CONSTANT(opline, opline->op1); @@ -6790,7 +6597,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -6812,7 +6618,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -6832,7 +6637,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -6844,14 +6648,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_smaller_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -6880,7 +6680,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -6893,13 +6692,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -6928,7 +6723,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -6941,13 +6735,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -6976,7 +6766,6 @@ is_smaller_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -6988,12 +6777,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { is_smaller_or_equal_true: - + ZEND_VM_SMART_BRANCH_TRUE_NONE(); ZVAL_TRUE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } else { is_smaller_or_equal_false: - + ZEND_VM_SMART_BRANCH_FALSE_NONE(); ZVAL_FALSE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -7024,7 +6813,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -7072,7 +6860,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -7162,9 +6949,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMP op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7177,8 +6962,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7191,8 +6974,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7204,9 +6985,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_T op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7219,8 +6998,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7233,8 +7010,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7246,9 +7021,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_ op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7261,8 +7034,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7275,8 +7046,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7288,9 +7057,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPE op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7303,8 +7070,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7317,14 +7082,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; zend_long offset; HashTable *ht; @@ -7377,41 +7139,38 @@ fetch_dim_r_index_undef: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -7471,7 +7230,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -7479,27 +7238,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container, *dim, *value; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: @@ -7522,7 +7279,7 @@ fetch_dim_r_slow: } else { zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7530,13 +7287,12 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7563,20 +7319,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -7602,9 +7351,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7629,10 +7380,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -7643,7 +7394,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7655,11 +7406,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -7670,7 +7432,7 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7678,20 +7440,13 @@ fetch_obj_r_finish: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -7710,9 +7465,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7737,10 +7494,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -7751,7 +7508,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7763,9 +7520,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -7776,7 +7543,7 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7801,26 +7568,24 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); @@ -7928,7 +7693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7936,7 +7701,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -7948,12 +7712,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -7972,7 +7732,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); @@ -7991,16 +7751,16 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -8017,7 +7777,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -8026,12 +7786,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -8046,7 +7805,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -8061,9 +7820,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -8122,9 +7884,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { @@ -8140,7 +7900,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } @@ -8155,11 +7915,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -8167,7 +7926,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C init_func_run_time_cache(&fbc->op_array); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -8190,13 +7949,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -8221,7 +7976,6 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; @@ -8231,18 +7985,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; SAVE_OPLINE(); - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -8261,7 +8007,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { if (call_info & ZEND_CALL_CLOSURE) { zend_object_release(ZEND_CLOSURE_OBJECT(func)); @@ -8275,14 +8021,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -8296,7 +8038,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -8335,8 +8076,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -8381,7 +8121,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -8415,7 +8155,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zend_ulong hval; @@ -8423,7 +8162,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -8450,6 +8189,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -8459,10 +8202,8 @@ num_index_prop: if (IS_CONST & (IS_CONST|IS_CV)) { /* avoid exception check */ - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -8485,29 +8226,22 @@ num_index_prop: } isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -8523,31 +8257,42 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); key = RT_CONSTANT(opline, opline->op1); - subject = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { array_key_exists_array: @@ -8560,158 +8305,17 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_CONST != IS_UNUSED) { - - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = RT_CONSTANT(opline, opline->op1); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = NULL; - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_CONST == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = RT_CONSTANT(opline, opline->op1); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8730,8 +8334,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -8798,27 +8400,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z } /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -8854,7 +8442,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zval *varname; zval *retval; zend_string *name, *tmp_name; @@ -8896,7 +8483,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -8915,7 +8502,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { ZVAL_NULL(retval); } else { @@ -9040,8 +8627,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { - - function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -9077,7 +8662,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -9108,13 +8692,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -9140,16 +8720,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP { USE_OPLINE - SAVE_OPLINE(); if (IS_CONST == IS_UNUSED) { + SAVE_OPLINE(); zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_CONST != IS_UNUSED) zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = RT_CONSTANT(opline, opline->op1); if (IS_CONST == IS_CONST) { @@ -9164,26 +8743,35 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -9260,7 +8848,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -9299,7 +8886,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -9383,7 +8969,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA zend_string *name, *tmp_name; HashTable *target_symbol_table; - SAVE_OPLINE(); varname = RT_CONSTANT(opline, opline->op1); @@ -9420,7 +9005,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U USE_OPLINE zval *value; int result; - zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; @@ -9457,8 +9041,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ @@ -9516,8 +9098,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -9585,26 +9165,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -9640,7 +9205,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; zend_long count; @@ -9651,9 +9215,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_ count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } if (UNEXPECTED(EG(exception))) { @@ -9663,10 +9229,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_ } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -9709,7 +9275,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CO ZEND_VM_NEXT_OPCODE(); } } else { - zval *op1; SAVE_OPLINE(); @@ -9724,8 +9289,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CO if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } @@ -9737,7 +9302,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; zend_string *type; @@ -9831,7 +9395,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -9846,7 +9409,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -9861,7 +9423,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -9933,7 +9494,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -9948,7 +9508,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -9984,7 +9543,6 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -10017,19 +9575,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = EX_VAR(opline->op2.var); if (IS_CONST == IS_CONST || @@ -10056,9 +9607,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10083,10 +9636,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -10097,7 +9650,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10109,11 +9662,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -10132,19 +9696,12 @@ fetch_obj_r_finish: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || @@ -10164,9 +9721,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10191,10 +9750,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -10205,7 +9764,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10217,9 +9776,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -10255,7 +9824,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -10268,7 +9836,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -10390,7 +9957,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -10402,10 +9968,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); } @@ -10485,7 +10047,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -10515,9 +10076,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -10576,8 +10140,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { - - function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -10613,7 +10175,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -10644,13 +10205,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -10675,7 +10232,6 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; @@ -10687,16 +10243,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H SAVE_OPLINE(); function_name = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -10728,14 +10276,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -10749,7 +10293,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -10788,7 +10331,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -10868,7 +10410,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zend_ulong hval; @@ -10903,6 +10444,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -10914,8 +10459,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -10941,25 +10484,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || @@ -10976,26 +10512,37 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -11013,13 +10560,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -11042,8 +10588,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -11111,26 +10655,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -11166,7 +10695,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = EX_VAR(opline->op1.var); @@ -11177,7 +10705,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = EX_VAR(opline->op1.var); @@ -11188,7 +10715,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_S static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = EX_VAR(opline->op1.var); @@ -11199,7 +10725,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SP static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -11238,7 +10763,6 @@ add_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -11277,7 +10801,6 @@ sub_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -11319,7 +10842,6 @@ mul_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = EX_VAR(opline->op1.var); @@ -11347,7 +10869,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11369,7 +10890,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11389,7 +10909,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11401,14 +10920,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_smaller_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -11437,7 +10952,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11450,13 +10964,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -11485,7 +10995,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11498,13 +11007,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -11533,7 +11038,6 @@ is_smaller_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11545,12 +11049,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { is_smaller_or_equal_true: - + ZEND_VM_SMART_BRANCH_TRUE_NONE(); ZVAL_TRUE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } else { is_smaller_or_equal_false: - + ZEND_VM_SMART_BRANCH_FALSE_NONE(); ZVAL_FALSE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -11581,7 +11085,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11629,7 +11132,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11677,7 +11179,6 @@ is_smaller_or_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11696,7 +11197,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11715,7 +11215,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11734,7 +11233,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -11747,7 +11245,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; @@ -11776,7 +11273,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; @@ -11926,9 +11422,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CO op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -11941,8 +11435,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -11955,8 +11447,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -11968,9 +11458,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_ op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -11983,8 +11471,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -11997,8 +11483,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12010,9 +11494,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARC op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12025,8 +11507,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12039,8 +11519,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12052,9 +11530,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVA op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12067,8 +11543,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12081,8 +11555,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12094,9 +11566,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_ op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12109,8 +11579,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12123,8 +11591,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12136,9 +11602,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARC op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12151,8 +11615,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12165,8 +11627,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12178,9 +11638,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_ op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12193,8 +11651,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12207,8 +11663,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12220,9 +11674,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPE op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12235,8 +11687,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12249,14 +11699,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -12295,7 +11742,6 @@ add_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -12334,7 +11780,6 @@ sub_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -12376,7 +11821,6 @@ mul_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = EX_VAR(opline->op1.var); @@ -12404,7 +11848,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12426,7 +11869,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12446,7 +11888,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12458,14 +11899,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVA if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_smaller_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -12494,7 +11931,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12507,13 +11943,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -12542,7 +11974,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12555,13 +11986,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -12590,7 +12017,6 @@ is_smaller_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12602,12 +12028,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { is_smaller_or_equal_true: - + ZEND_VM_SMART_BRANCH_TRUE_NONE(); ZVAL_TRUE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } else { is_smaller_or_equal_false: - + ZEND_VM_SMART_BRANCH_FALSE_NONE(); ZVAL_FALSE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -12638,7 +12064,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12686,7 +12111,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12734,7 +12158,6 @@ is_smaller_or_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12753,7 +12176,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12772,7 +12194,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12907,9 +12328,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TM op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12922,8 +12341,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12936,8 +12353,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12949,9 +12364,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_ op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12964,8 +12377,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12978,8 +12389,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12991,9 +12400,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARC op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13006,8 +12413,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13020,8 +12425,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13033,9 +12436,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVA op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13048,8 +12449,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13062,8 +12461,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13075,9 +12472,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_ op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13090,8 +12485,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13104,8 +12497,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13117,9 +12508,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARC op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13132,8 +12521,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13146,8 +12533,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13159,9 +12544,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_ op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13174,8 +12557,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13188,8 +12569,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13201,9 +12580,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPE op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13216,8 +12593,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13230,27 +12605,23 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -13263,10 +12634,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1)); ZEND_VM_NEXT_OPCODE(); @@ -13277,7 +12647,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVAR_HANDLER(ZEN op1 = ZVAL_UNDEFINED_OP1(); } bitwise_not_function(EX_VAR(opline->result.var), op1); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13285,9 +12655,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z { USE_OPLINE zval *val; - zend_free_op free_op1; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { @@ -13302,7 +12671,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z } else { SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); @@ -13311,11 +12680,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + z = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_P(z) == IS_STRING) { zend_string *str = Z_STR_P(z); @@ -13334,17 +12702,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_ zend_string_release_ex(str, 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZEND_VM_NEXT_OPCODE(); @@ -13360,22 +12728,25 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_H } SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); if (i_zend_is_true(val)) { opline++; } else { opline = OP_JMP_ADDR(opline, opline->op2); } - zval_ptr_dtor_nogc(free_op1); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); @@ -13391,22 +12762,25 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_ } SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); if (i_zend_is_true(val)) { opline = OP_JMP_ADDR(opline, opline->op2); } else { opline++; } - zval_ptr_dtor_nogc(free_op1); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_INFO_P(val) == IS_TRUE)) { ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); @@ -13423,23 +12797,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER(ZEN } SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); if (i_zend_is_true(val)) { opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); } else { opline = OP_JMP_ADDR(opline, opline->op2); } - zval_ptr_dtor_nogc(free_op1); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; int ret; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -13458,7 +12834,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZE SAVE_OPLINE(); ret = i_zend_is_true(val); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; @@ -13472,11 +12848,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; int ret; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -13494,7 +12869,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(Z SAVE_OPLINE(); ret = i_zend_is_true(val); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline = OP_JMP_ADDR(opline, opline->op2); @@ -13519,22 +12894,68 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FREE_SPEC_TMPVA zval *var; USE_OPLINE - SAVE_OPLINE(); var = EX_VAR(opline->op1.var); - if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) { - zend_hash_iterator_del(Z_FE_ITER_P(var)); + if (Z_TYPE_P(var) != IS_ARRAY) { + SAVE_OPLINE(); + if (Z_FE_ITER_P(var) != (uint32_t)-1) { + zend_hash_iterator_del(Z_FE_ITER_P(var)); + } + zval_ptr_dtor_nogc(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - zval_ptr_dtor_nogc(var); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + + /* This is freeing an array. Use an inlined version of zval_ptr_dtor_nogc. */ + /* PHP only needs to save the opline and check for an exception if the last reference to the array was garbage collected (destructors of elements in the array could throw an exception) */ + if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Can only throw objects"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } while (0); + + zend_exception_save(); + Z_TRY_ADDREF_P(value); + zend_throw_exception_object(value); + zend_exception_restore(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; - zend_free_op free_op1; - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, value); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -13549,9 +12970,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_ { USE_OPLINE zval *val; - zend_free_op free_op1; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { @@ -13566,7 +12986,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_ } else { SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); @@ -13575,18 +12995,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + obj = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); do { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -13605,17 +13021,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND } } zend_throw_error(NULL, "__clone method called on non-object"); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -13626,16 +13043,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { zend_wrong_clone_call(clone, scope); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13643,13 +13060,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA { USE_OPLINE zend_op_array *new_op_array; - zend_free_op free_op1; zval *inc_filename; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + inc_filename = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (UNEXPECTED(EG(exception) != NULL)) { if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { destroy_op_array(new_op_array); @@ -13705,16 +13121,120 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + +yield_from_try_again: + if (Z_TYPE_P(val) == IS_ARRAY) { + ZVAL_COPY_VALUE(&generator->values, val); + if (Z_OPT_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); + } + Z_FE_POS(generator->values) = 0; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(val); + if (ce == zend_ce_generator) { + zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); + + Z_ADDREF_P(val); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zend_object_iterator *iter = ce->get_iterator(ce, val, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (!EG(exception)) { + zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(&generator->values, &iter->std); + } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; + } else { + zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + /* This is the default return value + * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; - zend_free_op free_op1; - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } else { zend_bool strict; @@ -13723,7 +13243,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN value = Z_REFVAL_P(value); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } } @@ -13747,12 +13267,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN zval_ptr_dtor(&tmp); } if (!EG(exception)) { - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13761,12 +13281,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TM USE_OPLINE zval *value; int result = 0; - zend_free_op free_op1; - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -13786,28 +13305,23 @@ type_check_resource: } if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13815,14 +13329,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13830,10 +13343,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -13893,7 +13405,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL op2 = ZVAL_UNDEFINED_OP2(); } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13902,11 +13414,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -13914,14 +13425,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -13965,11 +13472,10 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -13978,13 +13484,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14028,11 +13530,10 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14041,13 +13542,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14091,11 +13588,10 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14103,14 +13599,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14154,11 +13646,10 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14167,13 +13658,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14217,11 +13704,10 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14230,13 +13716,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14280,14 +13762,13 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -14295,14 +13776,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); boolean_xor_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -14310,11 +13790,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -14339,40 +13818,32 @@ fetch_dim_r_slow: zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -14399,9 +13870,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -14426,10 +13899,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -14440,7 +13913,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -14452,11 +13925,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -14468,26 +13952,19 @@ fetch_obj_r_copy: fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -14507,9 +13984,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -14534,10 +14013,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -14548,7 +14027,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -14560,9 +14039,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -14574,19 +14063,18 @@ fetch_obj_is_copy: fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -14694,7 +14182,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ zend_string_release_ex(op2_str, 0); } } while (0); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -14703,7 +14191,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -14713,11 +14200,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); @@ -14734,13 +14217,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); } @@ -14768,7 +14251,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); @@ -14794,11 +14277,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -14818,7 +14300,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); @@ -14829,9 +14311,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -14848,24 +14333,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { case_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { case_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14904,14 +14384,13 @@ case_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; int result; zend_ulong hval; zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -14939,6 +14418,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -14950,8 +14433,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -14975,27 +14456,20 @@ num_index_prop: isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -15012,30 +14486,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); - key = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); subject = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { @@ -15049,25 +14534,23 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -15085,7 +14568,7 @@ try_instanceof: ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -15102,21 +14585,18 @@ try_instanceof: } result = 0; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; zend_long offset; HashTable *ht; - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_index_array: @@ -15130,7 +14610,7 @@ fetch_dim_r_index_array: ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_NEXT_OPCODE(); @@ -15149,7 +14629,7 @@ fetch_dim_r_index_slow: dim++; } zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -15157,19 +14637,18 @@ fetch_dim_r_index_undef: ZVAL_NULL(EX_VAR(opline->result.var)); SAVE_OPLINE(); zend_undefined_offset(offset); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; zend_long offset; HashTable *ht; - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_index_array: @@ -15183,7 +14662,7 @@ fetch_dim_r_index_array: ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_NEXT_OPCODE(); @@ -15202,7 +14681,7 @@ fetch_dim_r_index_slow: dim++; } zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -15210,48 +14689,45 @@ fetch_dim_r_index_undef: ZVAL_NULL(EX_VAR(opline->result.var)); SAVE_OPLINE(); zend_undefined_offset(offset); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -15310,8 +14786,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND op2 = ZVAL_UNDEFINED_OP2(); } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -15319,26 +14795,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15382,12 +14853,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15395,13 +14865,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15445,12 +14911,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15458,13 +14923,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15508,26 +14969,21 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15571,12 +15027,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15584,13 +15039,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15634,12 +15085,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15647,13 +15097,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15697,42 +15143,39 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); boolean_xor_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *dim, *value; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: @@ -15755,42 +15198,34 @@ fetch_dim_r_slow: } else { zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -15816,9 +15251,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -15843,10 +15280,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -15857,7 +15294,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -15869,11 +15306,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -15884,28 +15332,21 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -15924,9 +15365,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -15951,10 +15394,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -15965,7 +15408,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -15977,9 +15420,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -15990,21 +15443,20 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); @@ -16111,8 +15563,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR zend_string_release_ex(op2_str, 0); } } while (0); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16120,7 +15572,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -16130,14 +15581,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -16151,13 +15598,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); } @@ -16175,17 +15622,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); @@ -16201,7 +15648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -16210,12 +15657,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -16230,12 +15676,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); @@ -16246,9 +15692,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -16265,24 +15714,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 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); if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { case_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { case_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -16307,7 +15751,7 @@ case_double: } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (result) { goto case_true; } else { @@ -16321,15 +15765,14 @@ case_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; int result; zend_ulong hval; zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -16356,6 +15799,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -16365,10 +15812,8 @@ num_index_prop: if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { /* avoid exception check */ - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -16391,29 +15836,22 @@ num_index_prop: } isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -16429,31 +15867,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); - key = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - subject = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { array_key_exists_array: @@ -16466,26 +15915,24 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -16503,7 +15950,7 @@ try_instanceof: ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -16520,23 +15967,20 @@ try_instanceof: } result = 0; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zend_free_op free_op1; zval *varname; zval *retval; zend_string *name, *tmp_name; HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(varname); @@ -16549,7 +15993,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } name = zval_try_get_tmp_string(varname, &tmp_name); if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -16571,7 +16015,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -16590,7 +16034,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { ZVAL_NULL(retval); } else { @@ -16601,7 +16045,7 @@ fetch_this: } if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -16657,11 +16101,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; - zend_free_op free_op1; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(varname); @@ -16674,7 +16117,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H } name = zval_try_get_tmp_string(varname, &tmp_name); if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } @@ -16685,7 +16128,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16695,13 +16138,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_ USE_OPLINE zval *value; int result; - zend_free_op free_op1; zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(varname); } else { @@ -16714,7 +16156,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (!value) { result = (opline->extended_value & ZEND_ISEMPTY); @@ -16733,20 +16175,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_ } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -16764,7 +16203,7 @@ try_instanceof: ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -16781,29 +16220,28 @@ try_instanceof: } result = 0; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_long count; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); while (1) { if (Z_TYPE_P(op1) == IS_ARRAY) { count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } if (UNEXPECTED(EG(exception))) { @@ -16813,10 +16251,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -16840,7 +16278,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL } ZVAL_LONG(EX_VAR(opline->result.var), count); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16859,11 +16297,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_H ZEND_VM_NEXT_OPCODE(); } } else { - zend_free_op free_op1; zval *op1; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); while (1) { if (Z_TYPE_P(op1) == IS_OBJECT) { ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); @@ -16874,12 +16311,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_H if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -16887,8 +16324,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zval *result = EX_VAR(opline->result.var); ZVAL_COPY(result, value); ZEND_VM_NEXT_OPCODE(); @@ -16897,14 +16333,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16912,14 +16347,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16927,10 +16361,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = EX_VAR(opline->op2.var); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -16990,7 +16423,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( op2 = ZVAL_UNDEFINED_OP2(); } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16999,14 +16432,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -17014,11 +16446,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = EX_VAR(opline->op2.var); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -17043,40 +16474,32 @@ fetch_dim_r_slow: zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = EX_VAR(opline->op2.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -17103,9 +16526,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -17130,10 +16555,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -17144,7 +16569,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -17156,11 +16581,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -17172,26 +16608,19 @@ fetch_obj_r_copy: fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -17211,9 +16640,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -17238,10 +16669,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -17252,7 +16683,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -17264,9 +16695,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -17278,19 +16719,18 @@ fetch_obj_is_copy: fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = EX_VAR(opline->op2.var); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -17398,7 +16838,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN zend_string_release_ex(op2_str, 0); } } while (0); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -17407,7 +16847,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -17417,11 +16856,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); @@ -17438,13 +16873,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); } @@ -17472,7 +16907,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); @@ -17498,11 +16933,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -17522,7 +16956,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); @@ -17533,9 +16967,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -17552,24 +16989,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { case_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { case_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -17608,14 +17040,13 @@ case_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; int result; zend_ulong hval; zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -17643,6 +17074,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -17654,8 +17089,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -17679,27 +17112,20 @@ num_index_prop: isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -17716,30 +17142,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); - key = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); subject = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { @@ -17753,13 +17190,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -17768,9 +17204,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); @@ -17780,9 +17215,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } } else if (!return_value) { if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -17836,7 +17271,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER { USE_OPLINE zval *retval_ptr; - zend_free_op free_op1; SAVE_OPLINE(); @@ -17846,9 +17280,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (!EX(return_value)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); @@ -17896,12 +17330,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HAND { USE_OPLINE zval *retval; - zend_free_op free_op1; zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); - retval = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { @@ -17936,51 +17369,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HAND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - do { - if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { - if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - value = Z_REFVAL_P(value); - if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { - break; - } - } - if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Can only throw objects"); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - } while (0); - - zend_exception_save(); - if (IS_TMP_VAR != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - - zend_throw_exception_object(value); - zend_exception_restore(); - - HANDLE_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (EXPECTED(0)) { @@ -17991,7 +17383,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(Z send_val_by_ref: ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, value); if (IS_TMP_VAR == IS_CONST) { @@ -18006,7 +17398,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_T { USE_OPLINE zval *value, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (EXPECTED(1)) { @@ -18017,7 +17408,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_T send_val_by_ref: ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, value); if (IS_TMP_VAR == IS_CONST) { @@ -18032,7 +17423,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEN { USE_OPLINE zval *arg, *param; - zend_free_op free_op1; SAVE_OPLINE(); @@ -18040,23 +17430,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEN zend_param_must_be_ref(EX(call)->func, opline->op2.num); } - arg = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + arg = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); param = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY(param, arg); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); switch (opline->extended_value) { case IS_NULL: @@ -18137,19 +17526,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC } } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *result; SAVE_OPLINE(); - array_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); @@ -18160,26 +17548,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_TMP_VAR != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -18192,7 +17587,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -18200,7 +17595,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *array_ref; SAVE_OPLINE(); @@ -18211,7 +17605,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z array_ptr = Z_REFVAL_P(array_ref); } } else { - array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); } if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { @@ -18267,7 +17661,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z if (IS_TMP_VAR == IS_VAR) { } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); @@ -18284,7 +17678,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z if (IS_TMP_VAR == IS_VAR) { } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -18294,7 +17688,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(Z { USE_OPLINE - if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); @@ -18303,13 +17698,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; int ret; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { if (IS_TMP_VAR == IS_VAR) { @@ -18321,7 +17715,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ ret = i_zend_is_true(value); if (UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -18346,19 +17740,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { if (IS_TMP_VAR & IS_VAR) { @@ -18386,18 +17779,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *result = EX_VAR(opline->result.var); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); @@ -18429,145 +17821,34 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - zval *val; - zend_free_op free_op1; - - SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); - zval_ptr_dtor_nogc(free_op1); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (Z_TYPE_P(val) == IS_ARRAY) { - ZVAL_COPY_VALUE(&generator->values, val); - if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { - Z_ADDREF_P(val); - } - Z_FE_POS(generator->values) = 0; - - } else if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(val); - if (ce == zend_ce_generator) { - zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - - if (IS_TMP_VAR != IS_TMP_VAR) { - Z_ADDREF_P(val); - } - - if (Z_ISUNDEF(new_gen->retval)) { - if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { - zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - zend_generator_yield_from(generator, new_gen); - } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); - } - ZEND_VM_NEXT_OPCODE(); - } - } else { - zend_object_iterator *iter = ce->get_iterator(ce, val, 0); - zval_ptr_dtor_nogc(free_op1); - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (!EG(exception)) { - zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); - } - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - } - - ZVAL_OBJ(&generator->values, &iter->std); - } - } else { - zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - /* This is the default return value - * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* This generator has no send target (though the generator we delegate to might have one) */ - generator->send_target = NULL; - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18609,7 +17890,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -18645,7 +17925,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var, *ret; uint32_t i; @@ -18702,7 +17981,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -18716,7 +17994,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -18741,7 +18019,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -18837,8 +18114,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -18847,7 +18122,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -18879,7 +18154,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -18906,26 +18181,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -18961,13 +18221,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_TMP_VAR == IS_CONST); } else if (opline->extended_value) { @@ -18980,22 +18239,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLE result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } } ZEND_HASH_FOREACH_END(); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -19037,20 +18293,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var; /* op1 and result are the same */ rope = (zend_string**)EX_VAR(opline->op1.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); rope[opline->extended_value] = Z_STR_P(var); if (UNEXPECTED(Z_REFCOUNTED_P(var))) { Z_ADDREF_P(var); } } else { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); @@ -19063,7 +18318,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDL ZVAL_UNDEFINED_OP2(); } rope[opline->extended_value] = zval_get_string_func(var); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -19073,7 +18328,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var, *ret; uint32_t i; @@ -19082,13 +18336,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL rope = (zend_string**)EX_VAR(opline->op1.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); rope[opline->extended_value] = Z_STR_P(var); if (UNEXPECTED(Z_REFCOUNTED_P(var))) { Z_ADDREF_P(var); } } else { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); @@ -19101,7 +18355,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL ZVAL_UNDEFINED_OP2(); } rope[opline->extended_value] = zval_get_string_func(var); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (UNEXPECTED(EG(exception))) { for (i = 0; i <= opline->extended_value; i++) { zend_string_release_ex(rope[i], 0); @@ -19130,7 +18384,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -19144,7 +18397,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -19169,8 +18422,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -19215,7 +18467,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -19246,43 +18498,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HAN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -19301,8 +18517,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -19311,7 +18525,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -19343,7 +18557,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -19369,27 +18583,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -19422,144 +18622,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *op1, *op2; + zend_bool result; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = NULL; - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_TMP_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); - - ZEND_VM_RETURN(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -19585,17 +18675,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN { USE_OPLINE - SAVE_OPLINE(); if (IS_TMP_VAR == IS_UNUSED) { + SAVE_OPLINE(); zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_TMP_VAR != IS_UNUSED) zval *retval_ref, *retval_ptr; - zend_free_op free_op1; zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - - retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CONST) { ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); @@ -19609,32 +18698,40 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -19648,7 +18745,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -19673,7 +18770,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -19769,8 +18865,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -19779,7 +18873,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -19811,7 +18905,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -19838,26 +18932,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -19893,19 +18972,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_string *type; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); type = zend_zval_get_type(op1); if (EXPECTED(type)) { ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); } else { ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -19948,7 +19026,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -19984,7 +19061,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var, *ret; uint32_t i; @@ -20041,7 +19117,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -20055,7 +19130,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -20080,7 +19155,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -20176,8 +19250,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -20186,7 +19258,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -20218,7 +19290,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -20245,26 +19317,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -20300,10 +19357,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *closure, *var; - closure = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + closure = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (opline->extended_value & ZEND_BIND_REF) { /* By-ref binding */ var = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); @@ -20333,17 +19389,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDL static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20367,17 +19415,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_increment_function(var_ptr); @@ -20393,10 +19440,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_R static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_increment_function(var_ptr); @@ -20412,17 +19458,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_R static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20447,17 +19485,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_decrement_function(var_ptr); @@ -20473,10 +19510,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_R static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_decrement_function(var_ptr); @@ -20492,15 +19528,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_R static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20523,17 +19553,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel increment_function(var_ptr); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); @@ -20547,15 +19576,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20578,17 +19601,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel decrement_function(var_ptr); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); @@ -20604,9 +19626,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); @@ -20616,9 +19637,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } } else if (!return_value) { if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -20672,7 +19693,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER { USE_OPLINE zval *retval_ptr; - zend_free_op free_op1; SAVE_OPLINE(); @@ -20682,9 +19702,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (!EX(return_value)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); @@ -20699,7 +19719,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER break; } - retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); @@ -20708,7 +19728,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); } else { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } break; } @@ -20723,7 +19743,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } while (0); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -20733,12 +19753,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND { USE_OPLINE zval *retval; - zend_free_op free_op1; zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); - retval = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { @@ -20773,53 +19792,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - do { - if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { - if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - value = Z_REFVAL_P(value); - if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { - break; - } - } - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Can only throw objects"); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - } while (0); - - zend_exception_save(); - if (IS_VAR != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - - zend_throw_exception_object(value); - zend_exception_restore(); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); -} - static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); @@ -20859,10 +19837,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *varptr, *arg; - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, varptr); @@ -20879,7 +19856,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *varptr, *arg; uint32_t arg_num = opline->op2.num; @@ -20888,7 +19864,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HA ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, varptr); @@ -20901,7 +19877,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HA ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, varptr); @@ -20920,7 +19896,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HA static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *varptr, *arg; uint32_t arg_num = opline->op2.num; @@ -20929,7 +19904,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, varptr); @@ -20942,7 +19917,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, varptr); @@ -20961,19 +19936,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *varptr, *arg; SAVE_OPLINE(); - varptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { - ZVAL_NEW_EMPTY_REF(arg); - ZVAL_NULL(Z_REFVAL_P(arg)); - ZEND_VM_NEXT_OPCODE(); - } - if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { @@ -20981,7 +19949,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND } ZVAL_REF(arg, Z_REF_P(varptr)); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } @@ -20989,7 +19957,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(Z { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (EXPECTED(0)) { @@ -21001,7 +19968,7 @@ send_var_by_ref: ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); @@ -21037,7 +20004,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_V { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (EXPECTED(1)) { @@ -21049,7 +20015,7 @@ send_var_by_ref: ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); @@ -21085,13 +20051,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (UNEXPECTED(Z_ISREF_P(varptr))) { @@ -21115,7 +20080,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN { USE_OPLINE zval *arg, *param; - zend_free_op free_op1; SAVE_OPLINE(); @@ -21123,23 +20087,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN zend_param_must_be_ref(EX(call)->func, opline->op2.num); } - arg = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + arg = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); param = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY(param, arg); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); switch (opline->extended_value) { case IS_NULL: @@ -21170,7 +20133,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -21221,19 +20184,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC } } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *result; SAVE_OPLINE(); - array_ptr = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ptr = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); @@ -21242,30 +20204,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE } Z_FE_POS_P(result) = 0; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_VAR != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -21278,7 +20247,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -21286,18 +20255,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *array_ref; SAVE_OPLINE(); if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } } else { - array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); } if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { @@ -21321,7 +20289,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); if (IS_VAR == IS_VAR) { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { @@ -21346,15 +20314,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); @@ -21369,9 +20337,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_VAR == IS_VAR) { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -21712,13 +20680,12 @@ fe_fetch_w_exit: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; int ret; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { if (IS_VAR == IS_VAR) { @@ -21730,7 +20697,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ ret = i_zend_is_true(value); if (UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -21755,19 +20722,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { if (IS_VAR & IS_VAR) { @@ -21795,18 +20761,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *result = EX_VAR(opline->result.var); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); @@ -21838,120 +20803,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - zval *val; - zend_free_op free_op1; - - SAVE_OPLINE(); - val = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); - zval_ptr_dtor_nogc(free_op1); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (Z_TYPE_P(val) == IS_ARRAY) { - ZVAL_COPY_VALUE(&generator->values, val); - if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { - Z_ADDREF_P(val); - } - Z_FE_POS(generator->values) = 0; - - zval_ptr_dtor_nogc(free_op1); - } else if (IS_VAR != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(val); - if (ce == zend_ce_generator) { - zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - - if (IS_VAR != IS_TMP_VAR) { - Z_ADDREF_P(val); - } - zval_ptr_dtor_nogc(free_op1); - - if (Z_ISUNDEF(new_gen->retval)) { - if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { - zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - zend_generator_yield_from(generator, new_gen); - } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); - } - ZEND_VM_NEXT_OPCODE(); - } - } else { - zend_object_iterator *iter = ce->get_iterator(ce, val, 0); - zval_ptr_dtor_nogc(free_op1); - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (!EG(exception)) { - zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); - } - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - } - - ZVAL_OBJ(&generator->values, &iter->std); - } - } else { - zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - /* This is the default return value - * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* This generator has no send target (though the generator we delegate to might have one) */ - generator->send_target = NULL; - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (IS_VAR == IS_CV) { @@ -21967,14 +20824,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; uint32_t arg_num = opline->op2.num; if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (IS_VAR == IS_CV) { @@ -21989,61 +20845,51 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -22054,16 +20900,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22100,13 +20954,16 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -22115,12 +20972,11 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: @@ -22144,7 +21000,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -22161,7 +21017,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -22192,64 +21048,53 @@ assign_dim_op_ret_null: } } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; zval *value; SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op2); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - var_ptr = Z_REFVAL_P(var_ptr); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); do { @@ -22262,16 +21107,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22285,31 +21138,30 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); do { @@ -22322,16 +21174,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -22344,27 +21204,28 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22372,16 +21233,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22408,16 +21267,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22425,16 +21282,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -22443,7 +21295,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HAN BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22451,21 +21303,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22490,22 +21337,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22513,11 +21354,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = RT_CONSTANT(opline, opline->op2); if (IS_VAR == IS_VAR @@ -22536,16 +21376,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -22554,16 +21390,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -22647,7 +21482,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -22656,7 +21506,7 @@ exit_assign_obj: ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -22665,34 +21515,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -22776,16 +21621,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -22794,34 +21654,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -22905,16 +21760,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -22923,16 +21793,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -22941,16 +21807,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23034,7 +21899,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -23043,7 +21923,7 @@ exit_assign_obj: ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23052,15 +21932,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -23080,11 +21958,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -23146,9 +22025,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -23160,7 +22037,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23168,27 +22045,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -23196,6 +22071,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -23217,7 +22093,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -23232,14 +22108,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23247,9 +22123,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -23263,9 +22139,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -23277,7 +22151,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23285,27 +22159,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -23313,6 +22185,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -23334,7 +22207,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -23349,14 +22222,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23364,9 +22237,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -23380,9 +22253,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -23394,7 +22265,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23402,15 +22273,13 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -23430,11 +22299,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -23496,9 +22366,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -23510,7 +22378,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23518,27 +22386,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -23546,27 +22406,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -23574,20 +22426,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_VAR == IS_UNUSED) { @@ -23607,9 +22453,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23617,17 +22463,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -23650,7 +22490,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -23702,8 +22542,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { - - function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -23739,7 +22577,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -23770,13 +22607,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -23872,21 +22705,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -23911,7 +22743,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -23991,14 +22822,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; zend_ulong hval; zend_string *key; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); do { @@ -24049,7 +22879,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -24068,28 +22898,25 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); do { @@ -24107,10 +22934,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24133,8 +22971,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -24143,7 +22979,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -24151,7 +22987,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -24173,10 +23009,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -24188,7 +23024,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -24203,26 +23039,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -24258,13 +23079,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_VAR == IS_CONST); } else if (opline->extended_value) { @@ -24277,46 +23097,39 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLE result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } } ZEND_HASH_FOREACH_END(); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -24327,16 +23140,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_ && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -24373,13 +23194,16 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -24388,18 +23212,17 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); assign_dim_op_new_array: - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { @@ -24417,7 +23240,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -24434,7 +23257,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -24443,7 +23266,7 @@ assign_dim_op_new_array: } } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -24465,67 +23288,56 @@ assign_dim_op_ret_null: } } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *var_ptr; zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - var_ptr = Z_REFVAL_P(var_ptr); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -24537,16 +23349,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -24560,33 +23380,32 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -24598,16 +23417,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -24620,28 +23447,29 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24649,16 +23477,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24685,16 +23511,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24702,25 +23526,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24728,21 +23547,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24767,22 +23581,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *property, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24790,12 +23598,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_VAR == IS_VAR && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT @@ -24807,24 +23614,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_H zend_fetch_dimension_address_W(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -24832,16 +23635,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -24925,7 +23727,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -24933,8 +23750,8 @@ exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -24943,34 +23760,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25054,16 +23866,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25072,34 +23899,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25183,16 +24005,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25201,17 +24038,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -25219,16 +24052,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25312,7 +24144,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -25320,8 +24167,8 @@ exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25330,15 +24177,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -25358,11 +24203,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -25370,7 +24216,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25393,7 +24239,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -25407,7 +24253,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -25416,7 +24262,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -25424,10 +24270,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25436,9 +24280,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25446,27 +24290,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -25474,6 +24316,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -25486,7 +24329,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25495,7 +24338,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25509,31 +24352,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -25541,10 +24384,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25553,9 +24394,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25563,27 +24404,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -25591,6 +24430,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -25603,7 +24443,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25612,7 +24452,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25626,31 +24466,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -25658,10 +24498,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25670,9 +24508,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25680,15 +24518,13 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -25708,11 +24544,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -25720,7 +24557,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25743,7 +24580,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -25757,7 +24594,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -25766,7 +24603,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -25774,10 +24611,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25786,9 +24621,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25796,20 +24631,14 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_VAR == IS_UNUSED) { @@ -25829,9 +24658,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25839,18 +24668,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -25872,8 +24695,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25924,9 +24747,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { @@ -25942,7 +24763,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } @@ -25957,11 +24778,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -25969,7 +24789,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V init_func_run_time_cache(&fbc->op_array); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -25992,13 +24812,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -26023,21 +24839,20 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -26062,8 +24877,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -26108,7 +24922,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -26142,15 +24956,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; zval *offset; zend_ulong hval; zend_string *key; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -26200,7 +25013,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -26219,30 +25032,27 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -26259,107 +25069,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); - } while (0); - - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26378,8 +25107,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -26388,7 +25115,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -26396,7 +25123,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -26418,10 +25145,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -26433,7 +25160,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -26447,27 +25174,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -26500,66 +25213,122 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26567,27 +25336,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26595,23 +25356,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *variable_ptr; zval *value_ptr; SAVE_OPLINE(); - value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && + if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -26627,161 +25383,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - } - } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: @@ -26805,7 +25419,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -26822,7 +25436,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -26853,23 +25467,21 @@ assign_dim_op_ret_null: } } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26877,16 +25489,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26913,15 +25523,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -26941,11 +25549,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -27007,9 +25616,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -27021,7 +25628,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27029,27 +25636,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -27057,6 +25662,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -27078,7 +25684,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -27093,14 +25699,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27108,9 +25714,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -27124,9 +25730,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -27138,7 +25742,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27146,27 +25750,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -27174,6 +25776,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -27195,7 +25798,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -27210,14 +25813,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27225,9 +25828,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -27241,9 +25844,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -27255,7 +25856,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27263,15 +25864,13 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -27291,11 +25890,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -27357,9 +25957,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -27371,7 +25969,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27421,8 +26019,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { - - function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -27458,7 +26054,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -27489,13 +26084,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -27521,17 +26112,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN { USE_OPLINE - SAVE_OPLINE(); if (IS_VAR == IS_UNUSED) { + SAVE_OPLINE(); zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_VAR != IS_UNUSED) zval *retval_ref, *retval_ptr; - zend_free_op free_op1; zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - - retval_ref = retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ref = retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CONST) { ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); @@ -27545,26 +26135,35 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -27641,21 +26240,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -27680,7 +26278,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -27791,8 +26388,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -27801,7 +26396,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -27809,7 +26404,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -27831,10 +26426,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -27846,7 +26441,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -27861,26 +26456,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -27949,44 +26529,39 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_string *type; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); type = zend_zval_get_type(op1); if (EXPECTED(type)) { ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); } else { ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -27997,16 +26572,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HAND && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -28043,13 +26626,16 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28058,12 +26644,11 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: @@ -28087,7 +26672,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -28104,7 +26689,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -28135,64 +26720,53 @@ assign_dim_op_ret_null: } } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; zval *value; SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - var_ptr = Z_REFVAL_P(var_ptr); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -28205,16 +26779,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLE && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -28228,31 +26810,30 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -28265,16 +26846,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDL && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -28287,27 +26876,28 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28315,16 +26905,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28351,16 +26939,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28368,16 +26954,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -28386,7 +26967,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLE BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28394,21 +26975,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28433,22 +27009,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28456,11 +27026,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = EX_VAR(opline->op2.var); if (IS_VAR == IS_VAR @@ -28479,16 +27048,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -28497,16 +27062,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -28590,7 +27154,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -28599,7 +27178,7 @@ exit_assign_obj: ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28608,34 +27187,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -28719,16 +27293,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28737,34 +27326,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -28848,16 +27432,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28866,16 +27465,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -28884,16 +27479,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -28977,7 +27571,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -28986,7 +27595,7 @@ exit_assign_obj: ZVAL_COPY(EX_VAR(opline->result.var), value); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28995,15 +27604,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -29023,11 +27630,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -29089,9 +27697,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -29103,7 +27709,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29111,27 +27717,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -29139,6 +27743,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -29160,7 +27765,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -29175,14 +27780,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -29190,9 +27795,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -29206,9 +27811,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -29220,7 +27823,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29228,27 +27831,25 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -29256,6 +27857,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -29277,7 +27879,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -29292,14 +27894,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -29307,9 +27909,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -29323,9 +27925,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -29337,7 +27937,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29345,15 +27945,13 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: @@ -29373,11 +27971,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -29439,9 +28038,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -29453,7 +28050,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29461,27 +28058,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -29489,27 +28078,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -29517,23 +28098,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *variable_ptr; zval *value_ptr; SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && + if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -29549,27 +28125,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_VAR == IS_UNUSED) { @@ -29589,9 +28159,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29599,17 +28169,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -29632,7 +28196,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -29684,8 +28248,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { - - function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -29721,7 +28283,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -29752,13 +28313,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -29783,21 +28340,20 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -29822,7 +28378,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -29902,14 +28457,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; zend_ulong hval; zend_string *key; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = EX_VAR(opline->op2.var); do { @@ -29960,7 +28514,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -29979,28 +28533,25 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -30018,10 +28569,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER( break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30044,8 +28606,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -30054,7 +28614,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -30062,7 +28622,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -30084,10 +28644,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -30099,7 +28659,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -30114,26 +28674,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -30311,8 +28856,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -30320,10 +28865,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND SAVE_OPLINE(); obj = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - do { if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { @@ -30346,9 +28887,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -30369,7 +28911,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30422,25 +28964,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -30451,16 +28989,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONS && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -30497,11 +29043,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -30512,20 +29061,16 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -30538,16 +29083,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_ && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -30561,7 +29114,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -30572,20 +29128,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -30598,16 +29150,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -30620,7 +29180,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -30631,19 +29194,12 @@ post_incdec_object: static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_UNUSED == IS_CONST || @@ -30670,9 +29226,11 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -30697,10 +29255,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -30711,7 +29269,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -30723,11 +29281,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -30751,16 +29320,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -30769,7 +29333,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_ BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30777,21 +29341,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30799,19 +29358,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_UNUSED == IS_CONST || @@ -30831,9 +29383,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -30858,10 +29412,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -30872,7 +29426,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -30884,9 +29438,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -30922,22 +29486,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30945,16 +29503,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -30963,16 +29517,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31056,7 +29609,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -31074,34 +29642,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31185,10 +29748,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -31203,34 +29781,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31314,10 +29887,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -31332,16 +29920,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -31350,16 +29934,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31443,7 +30026,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -31461,20 +30059,14 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_UNUSED == IS_UNUSED) { @@ -31495,7 +30087,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -31503,17 +30095,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -31545,7 +30131,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -31580,7 +30165,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *class_name; USE_OPLINE @@ -31625,7 +30209,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -31637,10 +30220,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S object = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); } @@ -31720,7 +30299,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -31750,9 +30328,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -31811,8 +30392,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { - - function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -31848,7 +30427,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -31879,13 +30457,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -32018,15 +30592,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = RT_CONSTANT(opline, opline->op2); do { @@ -32044,7 +30615,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -32054,18 +30636,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_UNUSED == IS_CONST || @@ -32082,16 +30659,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -32113,8 +30702,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -32182,26 +30769,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -32237,25 +30809,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -32266,16 +30834,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32312,12 +30888,15 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); - zval_ptr_dtor_nogc(free_op2); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -32327,21 +30906,17 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -32353,16 +30928,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32376,11 +30959,14 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32388,21 +30974,17 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -32414,16 +30996,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -32436,11 +31026,14 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32448,20 +31041,13 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -32487,9 +31073,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32514,10 +31102,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -32528,7 +31116,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32540,11 +31128,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -32555,7 +31154,7 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32563,25 +31162,20 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32589,21 +31183,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32611,20 +31200,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -32643,9 +31225,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32670,10 +31254,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -32684,7 +31268,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32696,9 +31280,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -32709,7 +31303,7 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32734,22 +31328,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *property, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32757,17 +31345,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -32775,16 +31359,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -32868,7 +31451,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -32876,7 +31474,7 @@ exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -32886,34 +31484,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -32997,15 +31590,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -33015,34 +31623,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33126,15 +31729,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -33144,17 +31762,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -33162,16 +31776,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33255,7 +31868,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -33263,7 +31891,7 @@ exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -33273,20 +31901,14 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_UNUSED == IS_UNUSED) { @@ -33306,8 +31928,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -33315,18 +31937,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -33348,7 +31964,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -33357,20 +31973,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var; /* Compiler allocates the necessary number of zval slots to keep the rope */ rope = (zend_string**)EX_VAR(opline->result.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); rope[0] = Z_STR_P(var); if (UNEXPECTED(Z_REFCOUNTED_P(var))) { Z_ADDREF_P(var); } } else { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { rope[0] = zend_string_copy(Z_STR_P(var)); @@ -33383,7 +31998,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_H ZVAL_UNDEFINED_OP2(); } rope[0] = zval_get_string_func(var); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -33392,7 +32007,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_free_op free_op2; zval *class_name; USE_OPLINE @@ -33404,13 +32018,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR zend_class_entry *ce = CACHED_PTR(opline->extended_value); if (UNEXPECTED(ce == NULL)) { - class_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + class_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num); CACHE_PTR(opline->extended_value, ce); } Z_CE_P(EX_VAR(opline->result.var)) = ce; } else { - class_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + class_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); try_class_name: if (Z_TYPE_P(class_name) == IS_OBJECT) { Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); @@ -33430,7 +32044,7 @@ try_class_name: } } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -33438,7 +32052,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -33450,12 +32063,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T object = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -33474,7 +32083,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); @@ -33493,16 +32102,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -33519,7 +32128,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -33528,12 +32137,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -33548,7 +32156,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -33563,9 +32171,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -33624,9 +32235,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { @@ -33642,7 +32251,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } @@ -33657,11 +32266,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -33669,7 +32277,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U init_func_run_time_cache(&fbc->op_array); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -33692,13 +32300,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -33744,16 +32348,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -33770,10 +32371,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -33781,19 +32393,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -33809,159 +32416,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } - result = - (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); - -isset_object_finish: - zval_ptr_dtor_nogc(free_op2); - - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_UNUSED != IS_UNUSED) { - - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = NULL; - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = NULL; - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_UNUSED == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); +isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_RETURN(); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -33980,8 +32459,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -34048,27 +32525,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( } /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -34103,7 +32566,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *class_name; USE_OPLINE @@ -34189,8 +32651,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { - - function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -34226,7 +32686,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -34257,13 +32716,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -34289,16 +32744,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED { USE_OPLINE - SAVE_OPLINE(); if (IS_UNUSED == IS_UNUSED) { + SAVE_OPLINE(); zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_UNUSED != IS_UNUSED) zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = NULL; if (IS_UNUSED == IS_CONST) { @@ -34313,26 +32767,35 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -34446,8 +32909,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -34515,26 +32976,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -34567,7 +33013,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -34607,7 +33053,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_H ZEND_VM_NEXT_OPCODE(); } } else { - zval *op1; SAVE_OPLINE(); @@ -34622,8 +33067,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_H if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } @@ -34737,25 +33182,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -34766,16 +33207,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -34812,11 +33261,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -34827,20 +33279,16 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -34853,16 +33301,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -34876,7 +33332,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34887,20 +33346,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -34913,16 +33368,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -34935,7 +33398,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34946,19 +33412,12 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = EX_VAR(opline->op2.var); if (IS_UNUSED == IS_CONST || @@ -34985,9 +33444,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -35012,10 +33473,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -35026,7 +33487,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -35038,11 +33499,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -35061,16 +33533,11 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -35079,7 +33546,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HAN BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -35087,21 +33554,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -35109,19 +33571,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || @@ -35141,9 +33596,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -35168,10 +33625,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -35182,7 +33639,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -35194,9 +33651,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -35232,22 +33699,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -35255,16 +33716,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -35273,16 +33730,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35366,7 +33822,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -35384,34 +33855,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35495,10 +33961,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -35513,34 +33994,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35624,10 +34100,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -35642,16 +34133,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -35660,16 +34147,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35753,7 +34239,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -35771,20 +34272,14 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_UNUSED == IS_UNUSED) { @@ -35805,7 +34300,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -35813,17 +34308,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -35855,7 +34344,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -35890,7 +34378,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *class_name; USE_OPLINE @@ -35935,7 +34422,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -35947,10 +34433,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C object = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); } @@ -36030,7 +34512,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -36060,9 +34541,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -36121,8 +34605,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { - - function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -36158,7 +34640,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -36189,13 +34670,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -36241,15 +34718,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -36267,7 +34741,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -36277,18 +34762,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || @@ -36305,16 +34785,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -36336,8 +34828,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -36405,26 +34895,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -36460,7 +34935,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; op1 = EX_VAR(opline->op1.var); @@ -36483,7 +34957,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_ USE_OPLINE zval *val; - val = EX_VAR(opline->op1.var); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -36508,18 +34981,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36548,7 +35013,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36567,7 +35031,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36586,18 +35049,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RE static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36627,7 +35082,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36646,7 +35100,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36665,16 +35118,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RE static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36702,7 +35149,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36719,16 +35165,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_H static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36756,7 +35196,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36773,7 +35212,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *z; SAVE_OPLINE(); @@ -36802,8 +35240,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCO static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = EX_VAR(opline->op1.var); @@ -36821,20 +35259,23 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDL } SAVE_OPLINE(); + op1_type = IS_CV; if (i_zend_is_true(val)) { opline++; } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = EX_VAR(opline->op1.var); @@ -36852,20 +35293,23 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HAND } SAVE_OPLINE(); + op1_type = IS_CV; if (i_zend_is_true(val)) { opline = OP_JMP_ADDR(opline, opline->op2); } else { opline++; } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = EX_VAR(opline->op1.var); @@ -36884,19 +35328,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OP } SAVE_OPLINE(); + op1_type = IS_CV; if (i_zend_is_true(val)) { opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; int ret; @@ -36933,7 +35379,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; int ret; @@ -36971,7 +35416,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); @@ -36983,9 +35427,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } } else if (!return_value) { if (IS_CV & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -37040,7 +35484,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( USE_OPLINE zval *retval_ptr; - SAVE_OPLINE(); do { @@ -37100,7 +35543,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CV_HANDL USE_OPLINE zval *retval; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); @@ -37144,7 +35586,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC USE_OPLINE zval *value; - SAVE_OPLINE(); value = EX_VAR(opline->op1.var); @@ -37169,10 +35610,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC } while (0); zend_exception_save(); - if (IS_CV != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - + Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); zend_exception_restore(); @@ -37184,7 +35622,6 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SP USE_OPLINE zval *varptr, *arg; - varptr = EX_VAR(opline->op1.var); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { SAVE_OPLINE(); @@ -37225,19 +35662,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; SAVE_OPLINE(); varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { - ZVAL_NEW_EMPTY_REF(arg); - ZVAL_NULL(Z_REFVAL_P(arg)); - ZEND_VM_NEXT_OPCODE(); - } - if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { @@ -37252,7 +35682,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZE { USE_OPLINE zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; if (EXPECTED(0)) { @@ -37300,7 +35729,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_C { USE_OPLINE zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; if (EXPECTED(1)) { @@ -37349,7 +35777,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND USE_OPLINE zval *arg, *param; - SAVE_OPLINE(); if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { @@ -37368,7 +35795,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCO USE_OPLINE zval *val; - val = EX_VAR(opline->op1.var); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -37393,8 +35819,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -37402,10 +35828,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC SAVE_OPLINE(); obj = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - do { if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { @@ -37428,9 +35850,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -37451,7 +35874,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -37459,7 +35882,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; @@ -37553,7 +35975,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE { USE_OPLINE zend_op_array *new_op_array; - zval *inc_filename; SAVE_OPLINE(); @@ -37618,7 +36039,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *result; SAVE_OPLINE(); @@ -37634,20 +36054,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_CV != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -37673,7 +36100,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; SAVE_OPLINE(); @@ -37766,7 +36192,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; int ret; @@ -37815,7 +36240,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; @@ -37854,7 +36278,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *result = EX_VAR(opline->result.var); @@ -37893,14 +36316,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - zval *val; - SAVE_OPLINE(); - val = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + val = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); @@ -37909,9 +36329,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN HANDLE_EXCEPTION(); } +yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); - if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { + if (Z_OPT_REFCOUNTED_P(val)) { Z_ADDREF_P(val); } Z_FE_POS(generator->values) = 0; @@ -37921,9 +36342,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN if (ce == zend_ce_generator) { zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - if (IS_CV != IS_TMP_VAR) { - Z_ADDREF_P(val); - } + Z_ADDREF_P(val); if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { @@ -37968,6 +36387,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN ZVAL_OBJ(&generator->values, &iter->std); } + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; } else { zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); UNDEF_RESULT(); @@ -37999,7 +36421,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP USE_OPLINE zval *value; - value = EX_VAR(opline->op1.var); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); @@ -38036,9 +36457,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP zval_ptr_dtor(&tmp); } if (!EG(exception)) { - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -38051,11 +36472,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV zval *value; int result = 0; - value = EX_VAR(opline->op1.var); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -38077,12 +36497,8 @@ type_check_resource: SAVE_OPLINE(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } @@ -38239,7 +36655,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SP USE_OPLINE zval *varptr, *arg; - varptr = EX_VAR(opline->op1.var); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -38256,7 +36671,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE { USE_OPLINE zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { @@ -38278,7 +36692,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -38293,7 +36706,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -38308,7 +36720,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -38380,7 +36791,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -38391,14 +36801,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -38409,14 +36816,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38428,14 +36832,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38479,7 +36879,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38492,13 +36891,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HA if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38542,7 +36937,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38555,13 +36949,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_H if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38605,7 +36995,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38617,14 +37006,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38668,7 +37053,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38681,13 +37065,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38731,7 +37111,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38744,13 +37123,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38794,7 +37169,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -38809,7 +37183,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -38824,25 +37197,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -38853,16 +37222,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -38899,11 +37276,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -38914,7 +37294,6 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -38943,7 +37322,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -38960,7 +37339,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -38998,7 +37377,6 @@ assign_dim_op_ret_null: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; zval *value; @@ -39006,26 +37384,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLE value = RT_CONSTANT(opline, opline->op2); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - var_ptr = Z_REFVAL_P(var_ptr); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -39035,20 +37407,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -39061,16 +37429,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HAND && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -39084,7 +37460,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -39095,20 +37474,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -39121,16 +37496,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -39143,7 +37526,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -39154,7 +37540,6 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -39190,7 +37575,6 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -39198,8 +37582,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HAND zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39207,7 +37590,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -39215,8 +37597,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HAN zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39224,7 +37605,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -39257,7 +37637,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -39265,8 +37644,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_ zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39274,19 +37652,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CV == IS_CONST || @@ -39313,9 +37684,11 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -39340,10 +37713,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -39354,7 +37727,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -39366,11 +37739,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -39394,16 +37778,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -39412,7 +37791,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HAND BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39420,21 +37799,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39442,19 +37816,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CV == IS_CONST || @@ -39474,9 +37841,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -39501,10 +37870,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -39515,7 +37884,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -39527,9 +37896,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -39565,22 +37944,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39588,16 +37961,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -39606,16 +37975,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -39699,7 +38067,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -39717,34 +38100,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -39828,10 +38206,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -39846,34 +38239,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -39957,10 +38345,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -39975,16 +38378,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -39993,16 +38392,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -40086,7 +38484,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -40104,9 +38517,7 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40132,11 +38543,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -40198,9 +38610,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -40220,9 +38630,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40234,13 +38642,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -40248,6 +38656,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -40269,7 +38678,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -40284,14 +38693,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -40299,9 +38708,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -40315,9 +38724,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -40337,9 +38744,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40351,13 +38756,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -40365,6 +38770,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -40386,7 +38792,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -40401,14 +38807,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -40416,9 +38822,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -40432,9 +38838,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -40454,9 +38858,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40482,11 +38884,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -40548,9 +38951,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -40570,7 +38971,6 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -40578,27 +38978,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -40606,40 +38998,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_CV == IS_UNUSED) { @@ -40660,7 +39039,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -40668,17 +39047,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -40710,7 +39083,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -40832,7 +39204,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -40844,10 +39215,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S object = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); } @@ -40927,7 +39294,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -40957,9 +39323,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -40976,7 +39345,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -41015,7 +39383,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -41095,7 +39462,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; zend_ulong hval; @@ -41153,7 +39519,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -41172,7 +39538,7 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -41185,15 +39551,12 @@ num_index_dim: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = RT_CONSTANT(opline, opline->op2); do { @@ -41211,7 +39574,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -41221,7 +39595,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zend_ulong hval; @@ -41256,6 +39629,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -41267,8 +39644,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -41294,25 +39669,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CV == IS_CONST || @@ -41329,26 +39697,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -41366,20 +39745,18 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zend_bool result; @@ -41421,8 +39798,6 @@ try_instanceof: } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -41444,8 +39819,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -41513,26 +39886,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -41568,7 +39926,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string *varname; zval *value; zval *variable_ptr; @@ -41651,7 +40008,6 @@ check_indirect: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; @@ -41670,13 +40026,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } @@ -41684,14 +40039,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; zend_long offset; HashTable *ht; @@ -41744,7 +40096,6 @@ fetch_dim_r_index_undef: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; zend_long offset; HashTable *ht; @@ -41797,41 +40148,38 @@ fetch_dim_r_index_undef: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -41891,7 +40239,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -41899,26 +40247,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -41962,12 +40305,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -41975,13 +40317,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_H if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42025,12 +40363,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -42038,13 +40375,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_ if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42088,26 +40421,21 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42151,12 +40479,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -42164,13 +40491,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42214,12 +40537,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -42227,13 +40549,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42277,55 +40595,49 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); boolean_xor_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -42336,16 +40648,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -42382,12 +40702,15 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); - zval_ptr_dtor_nogc(free_op2); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -42397,7 +40720,6 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -42408,7 +40730,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H assign_dim_op_array: SEPARATE_ARRAY(container); assign_dim_op_new_array: - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { @@ -42426,7 +40748,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -42443,7 +40765,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -42452,7 +40774,7 @@ assign_dim_op_new_array: } } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -42474,7 +40796,7 @@ assign_dim_op_ret_null: } } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -42482,37 +40804,30 @@ assign_dim_op_ret_null: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *var_ptr; zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - var_ptr = Z_REFVAL_P(var_ptr); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42520,21 +40835,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -42546,16 +40857,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -42569,11 +40888,14 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42581,21 +40903,17 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -42607,16 +40925,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -42629,11 +40955,14 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42641,12 +40970,11 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container, *dim, *value; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: @@ -42669,7 +40997,7 @@ fetch_dim_r_slow: } else { zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42677,16 +41005,14 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42694,16 +41020,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42711,13 +41035,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42744,16 +41067,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42761,20 +41082,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -42800,9 +41114,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -42827,10 +41143,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -42841,7 +41157,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -42853,11 +41169,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -42868,7 +41195,7 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42876,25 +41203,20 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42902,21 +41224,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42924,20 +41241,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -42956,9 +41266,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -42983,10 +41295,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -42997,7 +41309,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -43009,9 +41321,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -43022,7 +41344,7 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43047,22 +41369,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *property, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43070,17 +41386,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -43088,16 +41400,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43181,7 +41492,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -43189,7 +41515,7 @@ exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43199,34 +41525,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43310,15 +41631,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43328,34 +41664,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43439,15 +41770,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43457,17 +41803,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -43475,16 +41817,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43568,7 +41909,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -43576,7 +41932,7 @@ exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43586,9 +41942,7 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -43614,11 +41968,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -43626,7 +41981,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -43649,7 +42004,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -43663,7 +42018,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -43672,7 +42027,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -43680,10 +42035,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -43692,7 +42045,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -43702,9 +42055,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -43716,13 +42067,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -43730,6 +42081,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -43742,7 +42094,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -43751,7 +42103,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -43765,31 +42117,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -43797,10 +42149,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -43809,7 +42159,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -43819,9 +42169,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -43833,13 +42181,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -43847,6 +42195,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -43859,7 +42208,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -43868,7 +42217,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -43882,31 +42231,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -43914,10 +42263,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -43926,7 +42273,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -43936,9 +42283,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -43964,11 +42309,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -43976,7 +42322,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -43999,7 +42345,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -44013,7 +42359,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -44022,7 +42368,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -44030,10 +42376,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -44042,7 +42386,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -44052,20 +42396,14 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_CV == IS_UNUSED) { @@ -44085,8 +42423,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -44094,18 +42432,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -44127,7 +42459,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -44136,13 +42468,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); @@ -44250,7 +42581,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -44258,7 +42589,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -44270,12 +42600,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA object = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -44294,7 +42620,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); @@ -44313,16 +42639,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -44339,7 +42665,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -44348,12 +42674,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -44368,7 +42693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -44383,9 +42708,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -44402,7 +42730,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -44441,8 +42768,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -44487,7 +42813,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -44521,7 +42847,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; zval *offset; zend_ulong hval; @@ -44529,7 +42854,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -44579,7 +42904,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -44598,13 +42923,13 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -44612,16 +42937,13 @@ num_index_dim: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -44638,10 +42960,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -44649,7 +42982,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zend_ulong hval; @@ -44657,7 +42989,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_ SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -44684,6 +43016,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -44693,10 +43029,8 @@ num_index_prop: if (IS_CV & (IS_CONST|IS_CV)) { /* avoid exception check */ - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -44719,29 +43053,22 @@ num_index_prop: } isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -44757,31 +43084,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); key = EX_VAR(opline->op1.var); - subject = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { array_key_exists_array: @@ -44794,110 +43132,17 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op2); - - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_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, &free_op2 EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *op1, *op2; - zend_bool result; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - 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, &free_op2 EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - - zval_ptr_dtor_nogc(free_op2); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = EX_VAR(opline->op1.var); - - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = EX_VAR(opline->op1.var); - - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -44916,8 +43161,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -44984,27 +43227,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -45037,118 +43266,161 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_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, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + 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); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + 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_identical_function(op1, op2); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_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, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *variable_ptr; zval *value_ptr; SAVE_OPLINE(); - value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && + if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -45164,7 +43436,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45172,7 +43444,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zend_bool result; @@ -45214,154 +43485,11 @@ try_instanceof: } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_CV != IS_UNUSED) { - - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CV & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_CV == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -45390,7 +43518,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -45407,7 +43535,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -45445,7 +43573,6 @@ assign_dim_op_ret_null: static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zval *varname; zval *retval; zend_string *name, *tmp_name; @@ -45487,7 +43614,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -45506,7 +43633,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable: %s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { ZVAL_NULL(retval); } else { @@ -45570,7 +43697,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -45578,8 +43704,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HAN zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45587,7 +43712,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -45595,8 +43719,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HA zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45623,9 +43746,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -45651,11 +43772,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -45717,9 +43839,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -45739,9 +43859,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -45753,13 +43871,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -45767,6 +43885,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -45788,7 +43907,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -45803,14 +43922,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -45818,9 +43937,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -45834,9 +43953,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -45856,9 +43973,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -45870,13 +43985,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -45884,6 +43999,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -45905,7 +44021,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -45920,14 +44036,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -45935,9 +44051,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -45951,9 +44067,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -45973,9 +44087,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -46001,11 +44113,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -46067,9 +44180,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -46090,16 +44201,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU { USE_OPLINE - SAVE_OPLINE(); if (IS_CV == IS_UNUSED) { + SAVE_OPLINE(); zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_CV != IS_UNUSED) zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST) { @@ -46114,32 +44224,40 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), cache_slot, retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -46178,7 +44296,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -46284,7 +44401,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL zend_string *name, *tmp_name; HashTable *target_symbol_table; - SAVE_OPLINE(); varname = EX_VAR(opline->op1.var); @@ -46326,25 +44442,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_S if (Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else { int result; SAVE_OPLINE(); result = !i_zend_is_true(value); - if (UNEXPECTED(EG(exception))) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH(result, 1); } } @@ -46358,25 +44464,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_S if (Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else { int result; SAVE_OPLINE(); result = !i_zend_is_true(value); - if (UNEXPECTED(EG(exception))) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH(result, 1); } } @@ -46385,7 +44481,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS USE_OPLINE zval *value; int result; - zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; @@ -46422,15 +44517,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zend_bool result; @@ -46472,8 +44564,6 @@ try_instanceof: } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46495,8 +44585,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -46564,26 +44652,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -46619,7 +44692,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - HashTable *ht; zval *value; zval *variable_ptr; @@ -46719,7 +44791,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; zend_long count; @@ -46730,9 +44801,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } if (UNEXPECTED(EG(exception))) { @@ -46742,10 +44815,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -46788,7 +44861,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDL ZEND_VM_NEXT_OPCODE(); } } else { - zval *op1; SAVE_OPLINE(); @@ -46803,8 +44875,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDL if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } @@ -46816,7 +44888,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; zend_string *type; @@ -46835,7 +44906,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -46850,7 +44920,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -46865,7 +44934,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -46937,7 +45005,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -46948,14 +45015,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -46966,14 +45030,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -46985,14 +45046,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47036,7 +45093,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47049,13 +45105,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDL if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47099,7 +45151,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47112,13 +45163,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HAND if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47162,7 +45209,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47174,14 +45220,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47225,7 +45267,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47238,13 +45279,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_H if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47288,7 +45325,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47301,13 +45337,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_ if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47351,7 +45383,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -47366,7 +45397,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -47381,25 +45411,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -47410,16 +45436,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDL && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -47456,11 +45490,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -47471,7 +45508,6 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -47500,7 +45536,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -47517,7 +45553,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -47555,7 +45591,6 @@ assign_dim_op_ret_null: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; zval *value; @@ -47563,26 +45598,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(Z value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } - var_ptr = Z_REFVAL_P(var_ptr); + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -47592,20 +45621,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -47618,16 +45643,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -47641,7 +45674,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -47652,20 +45688,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -47678,16 +45710,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLE && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -47700,7 +45740,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -47711,7 +45754,6 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -47747,7 +45789,6 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -47755,8 +45796,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47764,7 +45804,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -47772,8 +45811,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLE zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47781,7 +45819,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -47814,7 +45851,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -47822,8 +45858,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HAN zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47831,19 +45866,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST || @@ -47870,9 +45898,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -47897,10 +45927,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -47911,7 +45941,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -47923,11 +45953,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -47946,16 +45987,11 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -47964,7 +46000,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47972,21 +46008,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47994,19 +46025,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || @@ -48026,9 +46050,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -48053,10 +46079,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -48067,7 +46093,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -48079,9 +46105,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -48117,22 +46153,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -48140,16 +46170,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -48158,16 +46184,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48251,7 +46276,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -48269,34 +46309,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48380,10 +46415,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -48398,34 +46448,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48509,10 +46554,25 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -48527,16 +46587,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -48545,16 +46601,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48638,7 +46693,22 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: @@ -48656,9 +46726,7 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -48684,11 +46752,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -48750,9 +46819,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -48772,9 +46839,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -48786,13 +46851,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_TMP_VAR == IS_CV) { @@ -48800,6 +46865,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -48821,7 +46887,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -48836,14 +46902,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -48851,9 +46917,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -48867,9 +46933,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -48889,9 +46953,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -48903,13 +46965,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ try_assign_dim_array: SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); if (UNEXPECTED(variable_ptr == NULL)) { - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); zend_cannot_add_element(); goto assign_dim_error; } else if (IS_VAR == IS_CV) { @@ -48917,6 +46979,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -48938,7 +47001,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -48953,14 +47016,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -48968,9 +47031,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -48984,9 +47047,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -49006,9 +47067,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -49034,11 +47093,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -49100,9 +47160,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -49122,7 +47180,6 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -49130,27 +47187,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -49158,27 +47207,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *variable_ptr; zval *value_ptr; @@ -49186,15 +47227,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && + if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -49217,20 +47254,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_CV == IS_UNUSED) { @@ -49251,7 +47282,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -49259,17 +47290,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -49301,7 +47326,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -49423,7 +47447,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -49435,10 +47458,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA object = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); } @@ -49518,7 +47537,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -49548,9 +47566,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - + } else { + zval *free_op1 = EX_VAR(opline->op1.var); + if (free_op1 != object) { + GC_ADDREF(obj); /* For $this pointer */ + zval_ptr_dtor_nogc(free_op1); + } } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -49567,7 +47588,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -49606,7 +47626,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -49686,7 +47705,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; zend_ulong hval; @@ -49744,7 +47762,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -49763,7 +47781,7 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -49776,15 +47794,12 @@ num_index_dim: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -49802,7 +47817,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -49812,7 +47838,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zend_ulong hval; @@ -49847,6 +47872,10 @@ num_index_prop: goto isset_again; } else { value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } } if (!(opline->extended_value & ZEND_ISEMPTY)) { @@ -49858,8 +47887,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -49885,25 +47912,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || @@ -49920,26 +47940,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -49957,13 +47988,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -49986,8 +48016,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -50055,26 +48083,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -52011,8 +50024,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_SEND_VAR_NO_REF_SPEC_VAR_LABEL, (void*)&&ZEND_CATCH_SPEC_CONST_LABEL, (void*)&&ZEND_THROW_SPEC_CONST_LABEL, - (void*)&&ZEND_THROW_SPEC_TMP_LABEL, - (void*)&&ZEND_THROW_SPEC_VAR_LABEL, + (void*)&&ZEND_THROW_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_THROW_SPEC_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_THROW_SPEC_CV_LABEL, (void*)&&ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_LABEL, @@ -52310,28 +50323,28 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_CALL_TRAMPOLINE_SPEC_LABEL, (void*)&&ZEND_DISCARD_EXCEPTION_SPEC_LABEL, (void*)&&ZEND_YIELD_SPEC_CONST_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_CONST_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_CONST_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CONST_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CONST_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_CONST_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_TMP_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_TMP_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_TMP_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_TMP_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_TMP_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_TMP_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_TMP_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_VAR_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_VAR_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_VAR_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_VAR_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_VAR_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_VAR_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_UNUSED_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_UNUSED_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_UNUSED_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_UNUSED_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_UNUSED_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_UNUSED_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_UNUSED_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_CV_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_CV_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_CV_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CV_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CV_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_CV_CV_LABEL, (void*)&&ZEND_GENERATOR_RETURN_SPEC_CONST_LABEL, @@ -52344,8 +50357,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_RECV_VARIADIC_SPEC_UNUSED_LABEL, (void*)&&ZEND_SEND_UNPACK_SPEC_LABEL, (void*)&&ZEND_YIELD_FROM_SPEC_CONST_LABEL, - (void*)&&ZEND_YIELD_FROM_SPEC_TMP_LABEL, - (void*)&&ZEND_YIELD_FROM_SPEC_VAR_LABEL, + (void*)&&ZEND_YIELD_FROM_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_FROM_SPEC_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_YIELD_FROM_SPEC_CV_LABEL, (void*)&&ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_LABEL, @@ -53758,7 +51771,6 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); @@ -53770,9 +51782,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -54286,13 +52298,9 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR) ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CONST_TMP): - VM_TRACE(ZEND_YIELD_SPEC_CONST_TMP) - ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CONST_VAR): - VM_TRACE(ZEND_YIELD_SPEC_CONST_VAR) - ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_CASE(ZEND_YIELD_SPEC_CONST_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_CONST_TMPVAR) + ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_R_SPEC_CONST_UNUSED): VM_TRACE(ZEND_FETCH_R_SPEC_CONST_UNUSED) @@ -54914,6 +52922,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FE_FREE_SPEC_TMPVAR) ZEND_FE_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_THROW_SPEC_TMPVAR): + VM_TRACE(ZEND_THROW_SPEC_TMPVAR) + ZEND_THROW_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_VAL_SPEC_TMPVAR): VM_TRACE(ZEND_SEND_VAL_SPEC_TMPVAR) ZEND_SEND_VAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54930,6 +52942,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR) ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_FROM_SPEC_TMPVAR): + VM_TRACE(ZEND_YIELD_FROM_SPEC_TMPVAR) + ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_STRLEN_SPEC_TMPVAR): VM_TRACE(ZEND_STRLEN_SPEC_TMPVAR) ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55232,9 +53248,8 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); @@ -55244,9 +53259,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -55304,10 +53319,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_TMP) ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_THROW_SPEC_TMP): - VM_TRACE(ZEND_THROW_SPEC_TMP) - ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP): VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP) ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55348,10 +53359,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_QM_ASSIGN_SPEC_TMP) ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_FROM_SPEC_TMP): - VM_TRACE(ZEND_YIELD_FROM_SPEC_TMP) - ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST) ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55416,6 +53423,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR) ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_TMP_TMPVAR) + ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP) ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55424,14 +53435,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP) ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_TMP): - VM_TRACE(ZEND_YIELD_SPEC_TMP_TMP) - ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_VAR): - VM_TRACE(ZEND_YIELD_SPEC_TMP_VAR) - ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED): VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55518,9 +53521,8 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); @@ -55530,9 +53532,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -55590,10 +53592,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_VAR) ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_THROW_SPEC_VAR): - VM_TRACE(ZEND_THROW_SPEC_VAR) - ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_VAR_SPEC_VAR): VM_TRACE(ZEND_SEND_VAR_SPEC_VAR) ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55662,10 +53660,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_QM_ASSIGN_SPEC_VAR) ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_FROM_SPEC_VAR): - VM_TRACE(ZEND_YIELD_FROM_SPEC_VAR) - ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_VAR_SIMPLE_SPEC_VAR): VM_TRACE(ZEND_SEND_VAR_SIMPLE_SPEC_VAR) ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55934,6 +53928,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR) ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_VAR_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_VAR_TMPVAR) + ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_VAR_TMP): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_TMP) ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55950,10 +53948,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED) ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_VAR_TMP): - VM_TRACE(ZEND_YIELD_SPEC_VAR_TMP) - ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_VAR_VAR): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_VAR) ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55974,10 +53968,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_REF_SPEC_VAR_VAR) ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_VAR_VAR): - VM_TRACE(ZEND_YIELD_SPEC_VAR_VAR) - ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED): VM_TRACE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED) ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56390,13 +54380,9 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR) ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_UNUSED_TMP): - VM_TRACE(ZEND_YIELD_SPEC_UNUSED_TMP) - ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_UNUSED_VAR): - VM_TRACE(ZEND_YIELD_SPEC_UNUSED_VAR) - ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_CASE(ZEND_YIELD_SPEC_UNUSED_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_UNUSED_TMPVAR) + ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED): VM_TRACE(ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED) @@ -56600,7 +54586,6 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); @@ -56612,9 +54597,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_CV & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -57216,6 +55201,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR) ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_CV_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_CV_TMPVAR) + ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_CV_TMP): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_CV_TMP) ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57232,10 +55221,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED) ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CV_TMP): - VM_TRACE(ZEND_YIELD_SPEC_CV_TMP) - ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_CV_VAR): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_CV_VAR) ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57260,10 +55245,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INSTANCEOF_SPEC_CV_VAR) ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CV_VAR): - VM_TRACE(ZEND_YIELD_SPEC_CV_VAR) - ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED): VM_TRACE(ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED) ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -59532,8 +57513,8 @@ void zend_vm_init(void) ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, ZEND_CATCH_SPEC_CONST_HANDLER, ZEND_THROW_SPEC_CONST_HANDLER, - ZEND_THROW_SPEC_TMP_HANDLER, - ZEND_THROW_SPEC_VAR_HANDLER, + ZEND_THROW_SPEC_TMPVAR_HANDLER, + ZEND_THROW_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_THROW_SPEC_CV_HANDLER, ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_HANDLER, @@ -59831,28 +57812,28 @@ void zend_vm_init(void) ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, ZEND_YIELD_SPEC_CONST_CONST_HANDLER, - ZEND_YIELD_SPEC_CONST_TMP_HANDLER, - ZEND_YIELD_SPEC_CONST_VAR_HANDLER, + ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER, ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER, ZEND_YIELD_SPEC_CONST_CV_HANDLER, ZEND_YIELD_SPEC_TMP_CONST_HANDLER, - ZEND_YIELD_SPEC_TMP_TMP_HANDLER, - ZEND_YIELD_SPEC_TMP_VAR_HANDLER, + ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER, ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER, ZEND_YIELD_SPEC_TMP_CV_HANDLER, ZEND_YIELD_SPEC_VAR_CONST_HANDLER, - ZEND_YIELD_SPEC_VAR_TMP_HANDLER, - ZEND_YIELD_SPEC_VAR_VAR_HANDLER, + ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER, ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER, ZEND_YIELD_SPEC_VAR_CV_HANDLER, ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER, - ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER, - ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER, ZEND_YIELD_SPEC_UNUSED_CV_HANDLER, ZEND_YIELD_SPEC_CV_CONST_HANDLER, - ZEND_YIELD_SPEC_CV_TMP_HANDLER, - ZEND_YIELD_SPEC_CV_VAR_HANDLER, + ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER, ZEND_YIELD_SPEC_CV_UNUSED_HANDLER, ZEND_YIELD_SPEC_CV_CV_HANDLER, ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, @@ -59865,8 +57846,8 @@ void zend_vm_init(void) ZEND_RECV_VARIADIC_SPEC_UNUSED_HANDLER, ZEND_SEND_UNPACK_SPEC_HANDLER, ZEND_YIELD_FROM_SPEC_CONST_HANDLER, - ZEND_YIELD_FROM_SPEC_TMP_HANDLER, - ZEND_YIELD_FROM_SPEC_VAR_HANDLER, + ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER, + ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_YIELD_FROM_SPEC_CV_HANDLER, ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER, @@ -61156,7 +59137,7 @@ ZEND_API int zend_vm_kind(void) return ZEND_VM_KIND; } -static const void* ZEND_FASTCALL zend_vm_get_opcode_handler_ex(uint32_t spec, const zend_op* op) +static const uint32_t ZEND_FASTCALL zend_vm_get_opcode_handler_idx(uint32_t spec, const zend_op* op) { static const int zend_vm_decode[] = { _UNUSED_CODE, /* 0 = IS_UNUSED */ @@ -61183,20 +59164,20 @@ static const void* ZEND_FASTCALL zend_vm_get_opcode_handler_ex(uint32_t spec, co offset = offset * 2 + (op->extended_value & ZEND_ISEMPTY); } else if (spec & SPEC_RULE_SMART_BRANCH) { offset = offset * 3; - if ((op+1)->opcode == ZEND_JMPZ) { + if (op->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR)) { offset += 1; - } else if ((op+1)->opcode == ZEND_JMPNZ) { + } else if (op->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR)) { offset += 2; } } } - return zend_opcode_handlers[(spec & SPEC_START_MASK) + offset]; + return (spec & SPEC_START_MASK) + offset; } #if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op) { - return zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op); + return zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)]; } #endif @@ -61204,35 +59185,7 @@ static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op) { uint32_t spec = zend_spec_handlers[opcode]; - static const int zend_vm_decode[] = { - _UNUSED_CODE, /* 0 = IS_UNUSED */ - _CONST_CODE, /* 1 = IS_CONST */ - _TMP_CODE, /* 2 = IS_TMP_VAR */ - _UNUSED_CODE, /* 3 */ - _VAR_CODE, /* 4 = IS_VAR */ - _UNUSED_CODE, /* 5 */ - _UNUSED_CODE, /* 6 */ - _UNUSED_CODE, /* 7 */ - _CV_CODE /* 8 = IS_CV */ - }; - uint32_t offset = 0; - if (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type]; - if (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type]; - if (spec & SPEC_EXTRA_MASK) { - if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type]; - else if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED); - else if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num <= MAX_ARG_FLAG_NUM); - else if (spec & SPEC_RULE_SMART_BRANCH) { - offset = offset * 3; - if ((op+1)->opcode == ZEND_JMPZ) { - offset += 1; - } else if ((op+1)->opcode == ZEND_JMPNZ) { - offset += 2; - } - } - else if (spec & SPEC_RULE_ISSET) offset = offset * 2 + (op->extended_value & ZEND_ISEMPTY); - } - return zend_opcode_handler_funcs[(spec & SPEC_START_MASK) + offset]; + return zend_opcode_handler_funcs[zend_vm_get_opcode_handler_idx(spec, op)]; } #endif @@ -61246,7 +59199,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler(zend_op* op) zend_swap_operands(op); } } - op->handler = zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op); + op->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)]; } ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint32_t op2_info, uint32_t res_info) @@ -61320,6 +59273,38 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t spec = 2512 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; + case ZEND_IS_IDENTICAL: + if (op->op1_type < op->op2_type) { + zend_swap_operands(op); + } + if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { + if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { + break; + } + spec = 2537 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { + if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { + break; + } + spec = 2612 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + } + break; + case ZEND_IS_NOT_IDENTICAL: + if (op->op1_type < op->op2_type) { + zend_swap_operands(op); + } + if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { + if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { + break; + } + spec = 2687 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { + if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { + break; + } + spec = 2762 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + } + break; case ZEND_IS_EQUAL: if (op->op1_type < op->op2_type) { zend_swap_operands(op); @@ -61457,8 +59442,6 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t case ZEND_BW_AND: case ZEND_BW_XOR: case ZEND_BOOL_XOR: - case ZEND_IS_IDENTICAL: - case ZEND_IS_NOT_IDENTICAL: if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -61473,7 +59456,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t default: break; } - op->handler = zend_vm_get_opcode_handler_ex(spec, op); + op->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(spec, op)]; } ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex) diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 1eabc5687b..ccf23613f7 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -77,7 +77,7 @@ $vm_op_flags = array( "ZEND_VM_EXT_ARRAY_INIT" => 1<<19, "ZEND_VM_EXT_REF" => 1<<20, "ZEND_VM_EXT_FETCH_REF" => 1<<21, - "ZEND_VM_EXT_DIM_OBJ_WRITE" => 1<<22, + "ZEND_VM_EXT_DIM_WRITE" => 1<<22, "ZEND_VM_EXT_MASK" => 0x0f000000, "ZEND_VM_EXT_NUM" => 0x01000000, "ZEND_VM_EXT_LAST_CATCH" => 0x02000000, @@ -134,7 +134,7 @@ $vm_ext_decode = array( "FETCH_REF" => ZEND_VM_EXT_FETCH_REF, "SRC" => ZEND_VM_EXT_SRC, "CACHE_SLOT" => ZEND_VM_EXT_CACHE_SLOT, - "DIM_OBJ_WRITE" => ZEND_VM_EXT_DIM_OBJ_WRITE, + "DIM_WRITE" => ZEND_VM_EXT_DIM_WRITE, ); $vm_kind_name = array( @@ -208,54 +208,32 @@ $op2_type = array( "TMPVARCV" => "(IS_TMP_VAR|IS_VAR|IS_CV)", ); -$op1_free = array( - "ANY" => "(free_op1 != NULL)", - "TMP" => "1", - "VAR" => "(free_op1 != NULL)", - "CONST" => "0", - "UNUSED" => "0", - "CV" => "0", - "TMPVAR" => "???", - "TMPVARCV" => "???", -); - -$op2_free = array( - "ANY" => "(free_op2 != NULL)", - "TMP" => "1", - "VAR" => "(free_op2 != NULL)", - "CONST" => "0", - "UNUSED" => "0", - "CV" => "0", - "TMPVAR" => "???", - "TMPVARCV" => "???", -); - $op1_get_zval_ptr = array( - "ANY" => "get_zval_ptr(opline->op1_type, opline->op1, &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "ANY" => "get_zval_ptr(opline->op1_type, opline->op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op1)", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)", - "TMPVAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "TMPVARCV" => "???", ); $op2_get_zval_ptr = array( - "ANY" => "get_zval_ptr(opline->op2_type, opline->op2, &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "ANY" => "get_zval_ptr(opline->op2_type, opline->op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op2)", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)", - "TMPVAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "TMPVARCV" => "???", ); $op1_get_zval_ptr_ptr = array( - "ANY" => "get_zval_ptr_ptr(opline->op1_type, opline->op1, &free_op1, \\1)", + "ANY" => "get_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)", @@ -264,9 +242,9 @@ $op1_get_zval_ptr_ptr = array( ); $op2_get_zval_ptr_ptr = array( - "ANY" => "get_zval_ptr_ptr(opline->op2_type, opline->op2, &free_op2, \\1)", + "ANY" => "get_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)", @@ -275,9 +253,9 @@ $op2_get_zval_ptr_ptr = array( ); $op1_get_zval_ptr_deref = array( - "ANY" => "get_zval_ptr_deref(opline->op1_type, opline->op1, &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "ANY" => "get_zval_ptr_deref(opline->op1_type, opline->op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op1)", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_deref_\\1(opline->op1.var EXECUTE_DATA_CC)", @@ -286,9 +264,9 @@ $op1_get_zval_ptr_deref = array( ); $op2_get_zval_ptr_deref = array( - "ANY" => "get_zval_ptr_deref(opline->op2_type, opline->op2, &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "ANY" => "get_zval_ptr_deref(opline->op2_type, opline->op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op2)", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_deref_\\1(opline->op2.var EXECUTE_DATA_CC)", @@ -297,31 +275,31 @@ $op2_get_zval_ptr_deref = array( ); $op1_get_zval_ptr_undef = array( - "ANY" => "get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "ANY" => "get_zval_ptr_undef(opline->op1_type, opline->op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op1)", "UNUSED" => "NULL", "CV" => "EX_VAR(opline->op1.var)", - "TMPVAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "TMPVARCV" => "EX_VAR(opline->op1.var)", ); $op2_get_zval_ptr_undef = array( - "ANY" => "get_zval_ptr_undef(opline->op2_type, opline->op2, &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "ANY" => "get_zval_ptr_undef(opline->op2_type, opline->op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op2)", "UNUSED" => "NULL", "CV" => "EX_VAR(opline->op2.var)", - "TMPVAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "TMPVARCV" => "EX_VAR(opline->op2.var)", ); $op1_get_zval_ptr_ptr_undef = array( - "ANY" => "get_zval_ptr_ptr_undef(opline->op1_type, opline->op1, &free_op1, \\1)", + "ANY" => "get_zval_ptr_ptr_undef(opline->op1_type, opline->op1, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "NULL", "CV" => "EX_VAR(opline->op1.var)", @@ -330,9 +308,9 @@ $op1_get_zval_ptr_ptr_undef = array( ); $op2_get_zval_ptr_ptr_undef = array( - "ANY" => "get_zval_ptr_ptr_undef(opline->op2_type, opline->op2, &free_op2, \\1)", + "ANY" => "get_zval_ptr_ptr_undef(opline->op2_type, opline->op2, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "NULL", "CV" => "EX_VAR(opline->op2.var)", @@ -341,53 +319,53 @@ $op2_get_zval_ptr_ptr_undef = array( ); $op1_get_obj_zval_ptr = array( - "ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op1)", "UNUSED" => "&EX(This)", "CV" => "_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)", - "TMPVAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "TMPVARCV" => "???", ); $op2_get_obj_zval_ptr = array( - "ANY" => "get_obj_zval_ptr(opline->op2_type, opline->op2, &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "ANY" => "get_obj_zval_ptr(opline->op2_type, opline->op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op2)", "UNUSED" => "&EX(This)", "CV" => "_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)", - "TMPVAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "TMPVARCV" => "???", ); $op1_get_obj_zval_ptr_undef = array( - "ANY" => "get_obj_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "ANY" => "get_obj_zval_ptr_undef(opline->op1_type, opline->op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op1)", "UNUSED" => "&EX(This)", "CV" => "EX_VAR(opline->op1.var)", - "TMPVAR" => "_get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "TMPVARCV" => "EX_VAR(opline->op1.var)", ); $op2_get_obj_zval_ptr_undef = array( - "ANY" => "get_obj_zval_ptr_undef(opline->op2_type, opline->op2, &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "ANY" => "get_obj_zval_ptr_undef(opline->op2_type, opline->op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op2)", "UNUSED" => "&EX(This)", "CV" => "EX_VAR(opline->op2.var)", - "TMPVAR" => "_get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "TMPVARCV" => "EX_VAR(opline->op2.var)", ); $op1_get_obj_zval_ptr_deref = array( - "ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op1)", "UNUSED" => "&EX(This)", "CV" => "_get_zval_ptr_cv_deref_\\1(opline->op1.var EXECUTE_DATA_CC)", @@ -396,9 +374,9 @@ $op1_get_obj_zval_ptr_deref = array( ); $op2_get_obj_zval_ptr_deref = array( - "ANY" => "get_obj_zval_ptr(opline->op2_type, opline->op2, &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "ANY" => "get_obj_zval_ptr(opline->op2_type, opline->op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT(opline, opline->op2)", "UNUSED" => "&EX(This)", "CV" => "_get_zval_ptr_cv_deref_\\1(opline->op2.var EXECUTE_DATA_CC)", @@ -407,9 +385,9 @@ $op2_get_obj_zval_ptr_deref = array( ); $op1_get_obj_zval_ptr_ptr = array( - "ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, &free_op1, \\1)", + "ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "&EX(This)", "CV" => "_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)", @@ -418,9 +396,9 @@ $op1_get_obj_zval_ptr_ptr = array( ); $op2_get_obj_zval_ptr_ptr = array( - "ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, &free_op2, \\1)", + "ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "&EX(This)", "CV" => "_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)", @@ -429,9 +407,9 @@ $op2_get_obj_zval_ptr_ptr = array( ); $op1_get_obj_zval_ptr_ptr_undef = array( - "ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, &free_op1, \\1)", + "ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "&EX(This)", "CV" => "EX_VAR(opline->op1.var)", @@ -440,9 +418,9 @@ $op1_get_obj_zval_ptr_ptr_undef = array( ); $op2_get_obj_zval_ptr_ptr_undef = array( - "ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, &free_op2, \\1)", + "ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "&EX(This)", "CV" => "EX_VAR(opline->op2.var)", @@ -451,31 +429,31 @@ $op2_get_obj_zval_ptr_ptr_undef = array( ); $op1_free_op = array( - "ANY" => "FREE_OP(free_op1)", - "TMP" => "zval_ptr_dtor_nogc(free_op1)", - "VAR" => "zval_ptr_dtor_nogc(free_op1)", + "ANY" => "FREE_OP(opline->op1_type, opline->op1.var)", + "TMP" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", "CONST" => "", "UNUSED" => "", "CV" => "", - "TMPVAR" => "zval_ptr_dtor_nogc(free_op1)", + "TMPVAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", "TMPVARCV" => "???", ); $op2_free_op = array( - "ANY" => "FREE_OP(free_op2)", - "TMP" => "zval_ptr_dtor_nogc(free_op2)", - "VAR" => "zval_ptr_dtor_nogc(free_op2)", + "ANY" => "FREE_OP(opline->op2_type, opline->op2.var)", + "TMP" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", "CONST" => "", "UNUSED" => "", "CV" => "", - "TMPVAR" => "zval_ptr_dtor_nogc(free_op2)", + "TMPVAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", "TMPVARCV" => "???", ); $op1_free_op_if_var = array( - "ANY" => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(free_op1);}", + "ANY" => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}", "TMP" => "", - "VAR" => "zval_ptr_dtor_nogc(free_op1)", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", "CONST" => "", "UNUSED" => "", "CV" => "", @@ -484,9 +462,9 @@ $op1_free_op_if_var = array( ); $op2_free_op_if_var = array( - "ANY" => "if (opline->op2_type == IS_VAR) {zval_ptr_dtor_nogc(free_op2);}", + "ANY" => "if (opline->op2_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));}", "TMP" => "", - "VAR" => "zval_ptr_dtor_nogc(free_op2)", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", "CONST" => "", "UNUSED" => "", "CV" => "", @@ -495,9 +473,9 @@ $op2_free_op_if_var = array( ); $op1_free_op_var_ptr = array( - "ANY" => "if (free_op1) {zval_ptr_dtor_nogc(free_op1);}", + "ANY" => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}", "TMP" => "", - "VAR" => "if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", "CONST" => "", "UNUSED" => "", "CV" => "", @@ -506,9 +484,9 @@ $op1_free_op_var_ptr = array( ); $op2_free_op_var_ptr = array( - "ANY" => "if (free_op2) {zval_ptr_dtor_nogc(free_op2);}", + "ANY" => "if (opline->op2_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));}", "TMP" => "", - "VAR" => "if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", "CONST" => "", "UNUSED" => "", "CV" => "", @@ -550,20 +528,20 @@ $op_data_type = array( ); $op_data_get_zval_ptr = array( - "ANY" => "get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data)", - "TMP" => "_get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC)", + "ANY" => "get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1)", + "TMP" => "_get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT((opline+1), (opline+1)->op1)", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_\\1((opline+1)->op1.var EXECUTE_DATA_CC)", - "TMPVAR" => "_get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC)", + "TMPVAR" => "_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)", "TMPVARCV" => "???", ); $op_data_get_zval_ptr_deref = array( - "ANY" => "get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data)", - "TMP" => "_get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC)", - "VAR" => "_get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC)", + "ANY" => "get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1)", + "TMP" => "_get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC)", "CONST" => "RT_CONSTANT((opline+1), (opline+1)->op1)", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_deref_\\1((opline+1)->op1.var EXECUTE_DATA_CC)", @@ -572,9 +550,9 @@ $op_data_get_zval_ptr_deref = array( ); $op_data_get_zval_ptr_ptr = array( - "ANY" => "get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, &free_op_data, \\1)", + "ANY" => "get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC)", + "VAR" => "_get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)", "CONST" => "NULL", "UNUSED" => "NULL", "CV" => "_get_zval_ptr_cv_\\1((opline+1)->op1.var EXECUTE_DATA_CC)", @@ -583,20 +561,20 @@ $op_data_get_zval_ptr_ptr = array( ); $op_data_free_op = array( - "ANY" => "FREE_OP(free_op_data)", - "TMP" => "zval_ptr_dtor_nogc(free_op_data)", - "VAR" => "zval_ptr_dtor_nogc(free_op_data)", + "ANY" => "FREE_OP((opline+1)->op1_type, (opline+1)->op1.var)", + "TMP" => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))", "CONST" => "", "UNUSED" => "", "CV" => "", - "TMPVAR" => "zval_ptr_dtor_nogc(free_op_data)", + "TMPVAR" => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))", "TMPVARCV" => "???", ); $op_data_free_op_var_ptr = array( - "ANY" => "if (free_op_data) {zval_ptr_dtor_nogc(free_op_data);}", + "ANY" => "if ((opline+1)->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));}", "TMP" => "", - "VAR" => "if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));", "CONST" => "", "UNUSED" => "", "CV" => "", @@ -771,7 +749,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name, $extra_sp $op1_get_obj_zval_ptr_deref, $op2_get_obj_zval_ptr_deref, $op1_get_obj_zval_ptr_ptr, $op2_get_obj_zval_ptr_ptr, $op1_get_obj_zval_ptr_ptr_undef, $op2_get_obj_zval_ptr_ptr_undef, - $op1_free, $op2_free, $op1_free_unfetched, $op2_free_unfetched, + $op1_free_unfetched, $op2_free_unfetched, $op1_free_op, $op2_free_op, $op1_free_op_if_var, $op2_free_op_if_var, $op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix, $op_data_type, $op_data_get_zval_ptr, @@ -782,8 +760,6 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name, $extra_sp $specialized_replacements = array( "/OP1_TYPE/" => $op1_type[$op1], "/OP2_TYPE/" => $op2_type[$op2], - "/OP1_FREE/" => $op1_free[$op1], - "/OP2_FREE/" => $op2_free[$op2], "/GET_OP1_ZVAL_PTR\(([^)]*)\)/" => $op1_get_zval_ptr[$op1], "/GET_OP2_ZVAL_PTR\(([^)]*)\)/" => $op2_get_zval_ptr[$op2], "/GET_OP1_ZVAL_PTR_DEREF\(([^)]*)\)/" => $op1_get_zval_ptr_deref[$op1], @@ -835,19 +811,19 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name, $extra_sp ($extra_spec['SMART_BRANCH'] == 1 ? "ZEND_VM_SMART_BRANCH_JMPZ(\\1, \\2)" : ($extra_spec['SMART_BRANCH'] == 2 ? - "ZEND_VM_SMART_BRANCH_JMPNZ(\\1, \\2)" : "")) + "ZEND_VM_SMART_BRANCH_JMPNZ(\\1, \\2)" : "ZEND_VM_SMART_BRANCH_NONE(\\1, \\2)")) : "ZEND_VM_SMART_BRANCH(\\1, \\2)", "/ZEND_VM_SMART_BRANCH_TRUE\(\s*\)/" => isset($extra_spec['SMART_BRANCH']) ? ($extra_spec['SMART_BRANCH'] == 1 ? "ZEND_VM_SMART_BRANCH_TRUE_JMPZ()" : ($extra_spec['SMART_BRANCH'] == 2 ? - "ZEND_VM_SMART_BRANCH_TRUE_JMPNZ()" : "")) + "ZEND_VM_SMART_BRANCH_TRUE_JMPNZ()" : "ZEND_VM_SMART_BRANCH_TRUE_NONE()")) : "ZEND_VM_SMART_BRANCH_TRUE()", "/ZEND_VM_SMART_BRANCH_FALSE\(\s*\)/" => isset($extra_spec['SMART_BRANCH']) ? ($extra_spec['SMART_BRANCH'] == 1 ? "ZEND_VM_SMART_BRANCH_FALSE_JMPZ()" : ($extra_spec['SMART_BRANCH'] == 2 ? - "ZEND_VM_SMART_BRANCH_FALSE_JMPNZ()" : "")) + "ZEND_VM_SMART_BRANCH_FALSE_JMPNZ()" : "ZEND_VM_SMART_BRANCH_FALSE_NONE()")) : "ZEND_VM_SMART_BRANCH_FALSE()", "/opline->extended_value\s*&\s*ZEND_ISEMPTY/" => isset($extra_spec['ISSET']) ? ($extra_spec['ISSET'] == 0 ? "0" : "1") @@ -983,44 +959,6 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name, $extra_sp break; } - /* Remove unused free_op1 and free_op2 declarations */ - if ($spec && preg_match_all('/^\s*zend_free_op\s+[^;]+;\s*$/m', $code, $matches, PREG_SET_ORDER)) { - $n = 0; - foreach ($matches as $match) { - $code = preg_replace('/'.preg_quote($match[0],'/').'/', "\$D$n", $code); - ++$n; - } - $del_free_op1 = (strpos($code, "free_op1") === false); - $del_free_op2 = (strpos($code, "free_op2") === false); - $del_free_op_data = (strpos($code, "free_op_data") === false); - $n = 0; - foreach ($matches as $match) { - $dcl = $match[0]; - $changed = 0; - if ($del_free_op1 && strpos($dcl, "free_op1") !== false) { - $dcl = preg_replace("/free_op1\s*,\s*/", "", $dcl); - $dcl = preg_replace("/free_op1\s*;/", ";", $dcl); - $changed = 1; - } - if ($del_free_op2 && strpos($dcl, "free_op2") !== false) { - $dcl = preg_replace("/free_op2\s*,\s*/", "", $dcl); - $dcl = preg_replace("/free_op2\s*;/", ";", $dcl); - $changed = 1; - } - if ($del_free_op_data && strpos($dcl, "free_op_data") !== false) { - $dcl = preg_replace("/free_op_data\s*,\s*/", "", $dcl); - $dcl = preg_replace("/free_op_data\s*;/", ";", $dcl); - $changed = 1; - } - if ($changed) { - $dcl = preg_replace("/,\s*;/", ";", $dcl); - $dcl = preg_replace("/zend_free_op\s*;/", "", $dcl); - } - $code = preg_replace("/\\\$D$n/", $dcl, $code); - ++$n; - } - } - /* Remove unnecessary ';' */ $code = preg_replace('/^\s*;\s*$/m', '', $code); @@ -2456,19 +2394,22 @@ function gen_vm($def, $skel) { strpos($line,"ZEND_VM_HOT_OBJ_TYPE_SPEC_HANDLER(") === 0) { // Parsing opcode handler's definition if (preg_match( - "/^ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_)?TYPE_SPEC_HANDLER\(\s*([A-Z_]+)\s*,\s*((?:[^(,]|\([^()]*|(?R)*\))*),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/", + "/^ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_)?TYPE_SPEC_HANDLER\(\s*([A-Z_|]+)\s*,\s*((?:[^(,]|\([^()]*|(?R)*\))*),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/", $line, $m) == 0) { die("ERROR ($def:$lineno): Invalid ZEND_VM_TYPE_HANDLER_HANDLER definition.\n"); } $hot = !empty($m[1]) ? $m[1] : false; - $orig_op = $m[2]; - if (!isset($opnames[$orig_op])) { - die("ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n"); - } - $orig_code = $opnames[$orig_op]; - $condition = $m[3]; + $orig_op_list = $m[2]; $code = $extra_num++; + foreach (explode('|', $orig_op_list) as $orig_op) { + if (!isset($opnames[$orig_op])) { + die("ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n"); + } + $orig_code = $opnames[$orig_op]; + $condition = $m[3]; + $opcodes[$orig_code]['type_spec'][$code] = $condition; + } $op = $m[4]; $op1 = parse_operand_spec($def, $lineno, $m[5], $flags1); $op2 = parse_operand_spec($def, $lineno, $m[6], $flags2); @@ -2480,7 +2421,6 @@ function gen_vm($def, $skel) { if (isset($opcodes[$code])) { die("ERROR ($def:$lineno): Opcode with name '$code' is already defined.\n"); } - $opcodes[$orig_code]['type_spec'][$code] = $condition; $used_extra_spec["TYPE"] = 1; $opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot,"is_type_spec"=>true); if (isset($m[10])) { @@ -2756,10 +2696,10 @@ function gen_vm($def, $skel) { out($f, "\n"); // Generate zend_vm_get_opcode_handler() function - out($f, "static const void* ZEND_FASTCALL zend_vm_get_opcode_handler_ex(uint32_t spec, const zend_op* op)\n"); + out($f, "static const uint32_t ZEND_FASTCALL zend_vm_get_opcode_handler_idx(uint32_t spec, const zend_op* op)\n"); out($f, "{\n"); if (!ZEND_VM_SPEC) { - out($f, "\treturn zend_opcode_handlers[spec];\n"); + out($f, "\treturn spec;\n"); } else { out($f, "\tstatic const int zend_vm_decode[] = {\n"); out($f, "\t\t_UNUSED_CODE, /* 0 = IS_UNUSED */\n"); @@ -2808,9 +2748,9 @@ function gen_vm($def, $skel) { if (isset($used_extra_spec["SMART_BRANCH"])) { out($f, "\t\t{$else}if (spec & SPEC_RULE_SMART_BRANCH) {\n"); out($f, "\t\t\toffset = offset * 3;\n"); - out($f, "\t\t\tif ((op+1)->opcode == ZEND_JMPZ) {\n"); + out($f, "\t\t\tif (op->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR)) {\n"); out($f, "\t\t\t\toffset += 1;\n"); - out($f, "\t\t\t} else if ((op+1)->opcode == ZEND_JMPNZ) {\n"); + out($f, "\t\t\t} else if (op->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR)) {\n"); out($f, "\t\t\t\toffset += 2;\n"); out($f, "\t\t\t}\n"); $else = "} else "; @@ -2820,16 +2760,16 @@ function gen_vm($def, $skel) { } out($f, "\t}\n"); } - out($f, "\treturn zend_opcode_handlers[(spec & SPEC_START_MASK) + offset];\n"); + out($f, "\treturn (spec & SPEC_START_MASK) + offset;\n"); } out($f, "}\n\n"); out($f, "#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC\n"); out($f, "static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op)\n"); out($f, "{\n"); if (!ZEND_VM_SPEC) { - out($f, "\treturn zend_vm_get_opcode_handler_ex(opcode, op);\n"); + out($f, "\treturn zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n"); } else { - out($f, "\treturn zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op);\n"); + out($f, "\treturn zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)];\n"); } out($f, "}\n"); out($f, "#endif\n\n"); @@ -2839,65 +2779,11 @@ function gen_vm($def, $skel) { out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID\n"); out($f,"static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op)\n"); out($f, "{\n"); - out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n"); + out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n"); if (!ZEND_VM_SPEC) { out($f, "\treturn zend_opcode_handler_funcs[spec];\n"); } else { - out($f, "\tstatic const int zend_vm_decode[] = {\n"); - out($f, "\t\t_UNUSED_CODE, /* 0 = IS_UNUSED */\n"); - out($f, "\t\t_CONST_CODE, /* 1 = IS_CONST */\n"); - out($f, "\t\t_TMP_CODE, /* 2 = IS_TMP_VAR */\n"); - out($f, "\t\t_UNUSED_CODE, /* 3 */\n"); - out($f, "\t\t_VAR_CODE, /* 4 = IS_VAR */\n"); - out($f, "\t\t_UNUSED_CODE, /* 5 */\n"); - out($f, "\t\t_UNUSED_CODE, /* 6 */\n"); - out($f, "\t\t_UNUSED_CODE, /* 7 */\n"); - out($f, "\t\t_CV_CODE /* 8 = IS_CV */\n"); - out($f, "\t};\n"); - out($f, "\tuint32_t offset = 0;\n"); - out($f, "\tif (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];\n"); - out($f, "\tif (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];\n"); - - if (isset($used_extra_spec["OP_DATA"]) || - isset($used_extra_spec["RETVAL"]) || - isset($used_extra_spec["QUICK_ARG"]) || - isset($used_extra_spec["SMART_BRANCH"]) || - isset($used_extra_spec["ISSET"])) { - - $else = ""; - out($f, "\tif (spec & SPEC_EXTRA_MASK) {\n"); - - if (isset($used_extra_spec["OP_DATA"])) { - out($f, "\t\t{$else}if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n"); - $else = "else "; - } - if (isset($used_extra_spec["RETVAL"])) { - out($f, "\t\t{$else}if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);\n"); - $else = "else "; - } - if (isset($used_extra_spec["QUICK_ARG"])) { - out($f, "\t\t{$else}if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num <= MAX_ARG_FLAG_NUM);\n"); - $else = "else "; - } - if (isset($used_extra_spec["SMART_BRANCH"])) { - out($f, "\t\t{$else}if (spec & SPEC_RULE_SMART_BRANCH) {\n"); - out($f, "\t\t\toffset = offset * 3;\n"); - out($f, "\t\t\tif ((op+1)->opcode == ZEND_JMPZ) {\n"); - out($f, "\t\t\t\toffset += 1;\n"); - out($f, "\t\t\t} else if ((op+1)->opcode == ZEND_JMPNZ) {\n"); - out($f, "\t\t\t\toffset += 2;\n"); - out($f, "\t\t\t}\n"); - out($f, "\t\t}\n"); - $else = "else "; - } - if (isset($used_extra_spec["ISSET"])) { - out($f, "\t\t{$else}if (spec & SPEC_RULE_ISSET) offset = offset * 2 + (op->extended_value & ZEND_ISEMPTY);\n"); - $else = "else "; - } - out($f, "\t}\n"); - } - - out($f, "\treturn zend_opcode_handler_funcs[(spec & SPEC_START_MASK) + offset];\n"); + out($f, "\treturn zend_opcode_handler_funcs[zend_vm_get_opcode_handler_idx(spec, op)];\n"); } out($f, "}\n\n"); out($f, "#endif\n\n"); @@ -2908,7 +2794,7 @@ function gen_vm($def, $skel) { out($f, "{\n"); out($f, "\tzend_uchar opcode = zend_user_opcodes[op->opcode];\n"); if (!ZEND_VM_SPEC) { - out($f, "\top->handler = zend_vm_get_opcode_handler(opcode, op);\n"); + out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n"); } else { out($f, "\n"); out($f, "\tif (zend_spec_handlers[op->opcode] & SPEC_RULE_COMMUTATIVE) {\n"); @@ -2916,7 +2802,7 @@ function gen_vm($def, $skel) { out($f, "\t\t\tzend_swap_operands(op);\n"); out($f, "\t\t}\n"); out($f, "\t}\n"); - out($f, "\top->handler = zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op);\n"); + out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)];\n"); } out($f, "}\n\n"); @@ -2925,7 +2811,7 @@ function gen_vm($def, $skel) { out($f, "{\n"); out($f, "\tzend_uchar opcode = zend_user_opcodes[op->opcode];\n"); if (!ZEND_VM_SPEC) { - out($f, "\top->handler = zend_vm_get_opcode_handler_ex(opcode, op);\n"); + out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n"); } else { out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n"); if (isset($used_extra_spec["TYPE"])) { @@ -2994,7 +2880,7 @@ function gen_vm($def, $skel) { out($f, "\t\t\tbreak;\n"); out($f, "\t}\n"); } - out($f, "\top->handler = zend_vm_get_opcode_handler_ex(spec, op);\n"); + out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(spec, op)];\n"); } out($f, "}\n\n"); diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 7aa1a93981..306ca3ee45 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -962,8 +962,8 @@ _(1859, ZEND_SEND_VAR_NO_REF_SPEC_VAR) \ _(1860, ZEND_CATCH_SPEC_CONST) \ _(1861, ZEND_THROW_SPEC_CONST) \ - _(1862, ZEND_THROW_SPEC_TMP) \ - _(1863, ZEND_THROW_SPEC_VAR) \ + _(1862, ZEND_THROW_SPEC_TMPVAR) \ + _(1863, ZEND_THROW_SPEC_TMPVAR) \ _(1865, ZEND_THROW_SPEC_CV) \ _(1866, ZEND_FETCH_CLASS_SPEC_UNUSED_CONST) \ _(1867, ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR) \ @@ -1165,28 +1165,28 @@ _(2158, ZEND_CALL_TRAMPOLINE_SPEC) \ _(2159, ZEND_DISCARD_EXCEPTION_SPEC) \ _(2160, ZEND_YIELD_SPEC_CONST_CONST) \ - _(2161, ZEND_YIELD_SPEC_CONST_TMP) \ - _(2162, ZEND_YIELD_SPEC_CONST_VAR) \ + _(2161, ZEND_YIELD_SPEC_CONST_TMPVAR) \ + _(2162, ZEND_YIELD_SPEC_CONST_TMPVAR) \ _(2163, ZEND_YIELD_SPEC_CONST_UNUSED) \ _(2164, ZEND_YIELD_SPEC_CONST_CV) \ _(2165, ZEND_YIELD_SPEC_TMP_CONST) \ - _(2166, ZEND_YIELD_SPEC_TMP_TMP) \ - _(2167, ZEND_YIELD_SPEC_TMP_VAR) \ + _(2166, ZEND_YIELD_SPEC_TMP_TMPVAR) \ + _(2167, ZEND_YIELD_SPEC_TMP_TMPVAR) \ _(2168, ZEND_YIELD_SPEC_TMP_UNUSED) \ _(2169, ZEND_YIELD_SPEC_TMP_CV) \ _(2170, ZEND_YIELD_SPEC_VAR_CONST) \ - _(2171, ZEND_YIELD_SPEC_VAR_TMP) \ - _(2172, ZEND_YIELD_SPEC_VAR_VAR) \ + _(2171, ZEND_YIELD_SPEC_VAR_TMPVAR) \ + _(2172, ZEND_YIELD_SPEC_VAR_TMPVAR) \ _(2173, ZEND_YIELD_SPEC_VAR_UNUSED) \ _(2174, ZEND_YIELD_SPEC_VAR_CV) \ _(2175, ZEND_YIELD_SPEC_UNUSED_CONST) \ - _(2176, ZEND_YIELD_SPEC_UNUSED_TMP) \ - _(2177, ZEND_YIELD_SPEC_UNUSED_VAR) \ + _(2176, ZEND_YIELD_SPEC_UNUSED_TMPVAR) \ + _(2177, ZEND_YIELD_SPEC_UNUSED_TMPVAR) \ _(2178, ZEND_YIELD_SPEC_UNUSED_UNUSED) \ _(2179, ZEND_YIELD_SPEC_UNUSED_CV) \ _(2180, ZEND_YIELD_SPEC_CV_CONST) \ - _(2181, ZEND_YIELD_SPEC_CV_TMP) \ - _(2182, ZEND_YIELD_SPEC_CV_VAR) \ + _(2181, ZEND_YIELD_SPEC_CV_TMPVAR) \ + _(2182, ZEND_YIELD_SPEC_CV_TMPVAR) \ _(2183, ZEND_YIELD_SPEC_CV_UNUSED) \ _(2184, ZEND_YIELD_SPEC_CV_CV) \ _(2185, ZEND_GENERATOR_RETURN_SPEC_CONST) \ @@ -1198,8 +1198,8 @@ _(2192, ZEND_RECV_VARIADIC_SPEC_UNUSED) \ _(2193, ZEND_SEND_UNPACK_SPEC) \ _(2194, ZEND_YIELD_FROM_SPEC_CONST) \ - _(2195, ZEND_YIELD_FROM_SPEC_TMP) \ - _(2196, ZEND_YIELD_FROM_SPEC_VAR) \ + _(2195, ZEND_YIELD_FROM_SPEC_TMPVAR) \ + _(2196, ZEND_YIELD_FROM_SPEC_TMPVAR) \ _(2198, ZEND_YIELD_FROM_SPEC_CV) \ _(2199, ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED) \ _(2200, ZEND_BIND_GLOBAL_SPEC_CV_CONST) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 3290d760be..6f7252c8f5 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -284,7 +284,7 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x00000000, 0x01040310, 0x00000003, - 0x0000a110, + 0x00040110, 0x00040310, 0x00001007, 0x00001001, @@ -329,7 +329,7 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x01000000, 0x00001001, 0x02042003, - 0x00000003, + 0x00000007, 0x00040771, 0x00000057, 0x0b000003, @@ -381,13 +381,13 @@ static uint32_t zend_vm_opcodes_flags[195] = { 0x00000071, 0x00000000, 0x00000000, - 0x0b000303, + 0x0b000703, 0x00000003, 0x00000020, 0x00003000, - 0x0000a110, + 0x00040110, 0x00000000, - 0x00000003, + 0x00000007, 0x00000105, 0x00040301, 0x00002003, diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index d06f44e889..60bcb66643 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -54,7 +54,7 @@ #define ZEND_VM_EXT_ARRAY_INIT 0x00080000 #define ZEND_VM_EXT_REF 0x00100000 #define ZEND_VM_EXT_FETCH_REF 0x00200000 -#define ZEND_VM_EXT_DIM_OBJ_WRITE 0x00400000 +#define ZEND_VM_EXT_DIM_WRITE 0x00400000 #define ZEND_VM_EXT_MASK 0x0f000000 #define ZEND_VM_EXT_NUM 0x01000000 #define ZEND_VM_EXT_LAST_CATCH 0x02000000 diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index b73a5963aa..d7531af285 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | @@ -20,6 +18,7 @@ #include "zend_interfaces.h" #include "zend_objects_API.h" #include "zend_weakrefs.h" +#include "zend_weakrefs_arginfo.h" typedef struct _zend_weakref { zend_object *referent; @@ -112,13 +111,13 @@ static void zend_weakref_free(zend_object *zo) { #define zend_weakref_unsupported(thing) \ zend_throw_error(NULL, "WeakReference objects do not support " thing); -static ZEND_COLD zval* zend_weakref_no_write(zval *object, zval *member, zval *value, void **rtc) { +static ZEND_COLD zval* zend_weakref_no_write(zend_object *object, zend_string *member, zval *value, void **rtc) { zend_weakref_unsupported("properties"); return &EG(uninitialized_zval); } -static ZEND_COLD zval* zend_weakref_no_read(zval *object, zval *member, int type, void **rtc, zval *rv) { +static ZEND_COLD zval* zend_weakref_no_read(zend_object *object, zend_string *member, int type, void **rtc, zval *rv) { if (!EG(exception)) { zend_weakref_unsupported("properties"); } @@ -126,29 +125,22 @@ static ZEND_COLD zval* zend_weakref_no_read(zval *object, zval *member, int type return &EG(uninitialized_zval); } -static ZEND_COLD zval *zend_weakref_no_read_ptr(zval *object, zval *member, int type, void **rtc) { +static ZEND_COLD zval *zend_weakref_no_read_ptr(zend_object *object, zend_string *member, int type, void **rtc) { zend_weakref_unsupported("property references"); return NULL; } -static ZEND_COLD int zend_weakref_no_isset(zval *object, zval *member, int hse, void **rtc) { +static ZEND_COLD int zend_weakref_no_isset(zend_object *object, zend_string *member, int hse, void **rtc) { if (hse != 2) { zend_weakref_unsupported("properties"); } return 0; } -static ZEND_COLD void zend_weakref_no_unset(zval *object, zval *member, void **rtc) { +static ZEND_COLD void zend_weakref_no_unset(zend_object *object, zend_string *member, void **rtc) { zend_weakref_unsupported("properties"); } -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(zend_weakref_create_arginfo, 0, 1, WeakReference, 0) - ZEND_ARG_TYPE_INFO(0, referent, IS_OBJECT, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(zend_weakref_get_arginfo, 0, 0, IS_OBJECT, 1) -ZEND_END_ARG_INFO() - ZEND_COLD ZEND_METHOD(WeakReference, __construct) { zend_throw_error(NULL, @@ -160,7 +152,7 @@ ZEND_METHOD(WeakReference, create) { zval *referent; - ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1,1) + ZEND_PARSE_PARAMETERS_START(1,1) Z_PARAM_OBJECT(referent) ZEND_PARSE_PARAMETERS_END(); @@ -173,16 +165,15 @@ ZEND_METHOD(WeakReference, create) ZEND_METHOD(WeakReference, get) { - ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 0, 0) - ZEND_PARSE_PARAMETERS_END(); + ZEND_PARSE_PARAMETERS_NONE(); zend_weakref_get(getThis(), return_value); } static const zend_function_entry zend_weakref_methods[] = { - ZEND_ME(WeakReference, __construct, NULL, ZEND_ACC_PUBLIC) - ZEND_ME(WeakReference, create, zend_weakref_create_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - ZEND_ME(WeakReference, get, zend_weakref_get_arginfo, ZEND_ACC_PUBLIC) + ZEND_ME(WeakReference, __construct, arginfo_class_WeakReference___construct, ZEND_ACC_PUBLIC) + ZEND_ME(WeakReference, create, arginfo_class_WeakReference_create, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(WeakReference, get, arginfo_class_WeakReference_get, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/Zend/zend_weakrefs.h b/Zend/zend_weakrefs.h index c8a65e2563..cf902f3dd4 100644 --- a/Zend/zend_weakrefs.h +++ b/Zend/zend_weakrefs.h @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | diff --git a/Zend/zend_weakrefs.stub.php b/Zend/zend_weakrefs.stub.php new file mode 100644 index 0000000000..52ae81c7b8 --- /dev/null +++ b/Zend/zend_weakrefs.stub.php @@ -0,0 +1,9 @@ +<?php + +final class WeakReference { + public function __construct(); + + public static function create(): WeakReference; + + public function get(): ?object; +} diff --git a/Zend/zend_weakrefs_arginfo.h b/Zend/zend_weakrefs_arginfo.h new file mode 100644 index 0000000000..abcd0c8d99 --- /dev/null +++ b/Zend/zend_weakrefs_arginfo.h @@ -0,0 +1,10 @@ +/* This is a generated file, edit the .stub.php file instead. */ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_WeakReference___construct, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_WeakReference_create, 0, 0, WeakReference, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_WeakReference_get, 0, 0, IS_OBJECT, 1) +ZEND_END_ARG_INFO() |