diff --git a/Zend/tests/ArrayAccess/bug41209.phpt b/Zend/tests/ArrayAccess/bug41209.phpt index 1a7ee8aa515c..f1bc4267d762 100644 --- a/Zend/tests/ArrayAccess/bug41209.phpt +++ b/Zend/tests/ArrayAccess/bug41209.phpt @@ -42,5 +42,6 @@ echo "Done\n"; Fatal error: Uncaught ErrorException: Undefined variable $id in %s:%d Stack trace: #0 %s(%d): env::errorHandler(2, 'Undefined varia...', '%s', %d) -#1 {main} +#1 %s(%d): cache->offsetExists(NULL) +#2 {main} thrown in %s on line %d diff --git a/Zend/tests/bitwise_not_precision_exception.phpt b/Zend/tests/bitwise_not_precision_exception.phpt index e28bf8f4e17b..87631788d561 100644 --- a/Zend/tests/bitwise_not_precision_exception.phpt +++ b/Zend/tests/bitwise_not_precision_exception.phpt @@ -12,4 +12,5 @@ try { } ?> --EXPECT-- +int(-1) The float INF is not representable as an int, cast occurred diff --git a/Zend/tests/bug38220.phpt b/Zend/tests/bug38220.phpt index 2700299a1026..3d7ef66195a5 100644 --- a/Zend/tests/bug38220.phpt +++ b/Zend/tests/bug38220.phpt @@ -67,6 +67,7 @@ A Object ) func1(): 1 after call func1 +before call func1 A::__destruct() before call close A Object @@ -75,7 +76,6 @@ A Object ) close(): 1 after call close -before call func1 A Object ( [i] => 2 diff --git a/Zend/tests/bug63206.phpt b/Zend/tests/bug63206.phpt index 6aba55eca1ba..9cb056d48b5c 100644 --- a/Zend/tests/bug63206.phpt +++ b/Zend/tests/bug63206.phpt @@ -22,8 +22,10 @@ set_error_handler(function() { $triggerNotice1++; $triggerNotice2++; ?> ---EXPECT-- +--EXPECTF-- Second handler -Internal handler + +Warning: Undefined variable $triggerInternalNotice in %s on line %d Second handler -Internal handler + +Warning: Undefined variable $triggerInternalNotice in %s on line %d diff --git a/Zend/tests/bug70662.phpt b/Zend/tests/bug70662.phpt index ab540c9d16e5..2bda8141bab4 100644 --- a/Zend/tests/bug70662.phpt +++ b/Zend/tests/bug70662.phpt @@ -14,5 +14,5 @@ var_dump($a); --EXPECT-- array(1) { ["b"]=> - int(2) + int(1) } diff --git a/Zend/tests/bug70785.phpt b/Zend/tests/bug70785.phpt index 05b1b6afa0a0..16789a436ab0 100644 --- a/Zend/tests/bug70785.phpt +++ b/Zend/tests/bug70785.phpt @@ -7,19 +7,32 @@ set_error_handler(function($no, $msg) { throw new Exception($msg); }); -try { +function smart_branch() { if ($a === null) { // ZEND_VM_SMART_BRANCH - undefined_function('Null'); + return 'branch'; } -} catch (Exception $e) { + return 'no branch'; } -try { +function next_opcode() { $c === 3; // ZEND_VM_NEXT_OPCODE - undefined_function(); + return 'done'; +} + +try { + smart_branch(); } catch (Exception $e) { + echo $e->getMessage(), PHP_EOL; } + +try { + next_opcode(); +} catch (Exception $e) { + echo $e->getMessage(), PHP_EOL; +} +echo "okey\n"; ?> -okey --EXPECT-- +Undefined variable $a +Undefined variable $c okey diff --git a/Zend/tests/bug72101.phpt b/Zend/tests/bug72101.phpt index 6362a7ccb303..64393f07ba98 100644 --- a/Zend/tests/bug72101.phpt +++ b/Zend/tests/bug72101.phpt @@ -79,9 +79,10 @@ $foo->bar($a, $b, $c); Fatal error: Uncaught Error: Class "DoesNotExists" not found in %s:%d Stack trace: #0 %s(%d): {closure:%s:%d}(2, 'MethodCallbackB...', '%s', 8) -#1 %sbug72101.php(%d): PHPUnit_Framework_MockObject_Stub_ReturnCallback->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) -#2 %sbug72101.php(%d): PHPUnit_Framework_MockObject_Matcher->invoked(Object(PHPUnit_Framework_MockObject_Invocation_Static)) -#3 %sbug72101.php(%d): PHPUnit_Framework_MockObject_InvocationMocker->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) -#4 %sbug72101.php(%d): Mock_MethodCallbackByReference_7b180d26->bar(0, 0, 0) -#5 {main} +#1 %sbug72101.php(%d): MethodCallbackByReference->callback(0, 0, 0) +#2 %sbug72101.php(%d): PHPUnit_Framework_MockObject_Stub_ReturnCallback->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) +#3 %sbug72101.php(%d): PHPUnit_Framework_MockObject_Matcher->invoked(Object(PHPUnit_Framework_MockObject_Invocation_Static)) +#4 %sbug72101.php(%d): PHPUnit_Framework_MockObject_InvocationMocker->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) +#5 %sbug72101.php(%d): Mock_MethodCallbackByReference_7b180d26->bar(0, 0, 0) +#6 {main} thrown in %sbug72101.php on line %d diff --git a/Zend/tests/bug76534.phpt b/Zend/tests/bug76534.phpt index c9c897110d6c..9cec1962773b 100644 --- a/Zend/tests/bug76534.phpt +++ b/Zend/tests/bug76534.phpt @@ -10,8 +10,12 @@ $x = "foo"; $y = &$x["2bar"]; ?> --EXPECTF-- -Fatal error: Uncaught Exception: Illegal string offset "2bar" in %s:%d +Fatal error: Uncaught Error: Cannot create references to/from string offsets in %s:%d +Stack trace: +#0 {main} + +Next Exception: Illegal string offset "2bar" in %s:%d Stack trace: #0 %s(%d): {closure:%s:%d}(2, 'Illegal string ...', '%s', 7) #1 {main} - thrown in %sbug76534.php on line %d + thrown in %s on line %d \ No newline at end of file diff --git a/Zend/tests/bug78598.phpt b/Zend/tests/bug78598.phpt index 7e3559f27c26..976040204865 100644 --- a/Zend/tests/bug78598.phpt +++ b/Zend/tests/bug78598.phpt @@ -25,7 +25,31 @@ var_dump($my_var); ?> --EXPECT-- -int(0) -int(0) -int(0) -int(0) +array(1) { + [0]=> + string(3) "xyz" +} +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + string(3) "xyz" + } + } +} +array(1) { + ["foo"]=> + string(3) "xyz" +} +array(1) { + ["foo"]=> + array(1) { + ["bar"]=> + array(1) { + ["baz"]=> + string(3) "xyz" + } + } +} diff --git a/Zend/tests/bug79784.phpt b/Zend/tests/bug79784.phpt index be1cd729e969..83e64626bba7 100644 --- a/Zend/tests/bug79784.phpt +++ b/Zend/tests/bug79784.phpt @@ -15,6 +15,18 @@ var_dump($a); ?> --EXPECT-- -NULL -NULL -NULL +array(1) { + [""]=> + string(1) "x" +} +array(1) { + [""]=> + string(1) "x" +} +array(1) { + [""]=> + array(1) { + [""]=> + string(1) "x" + } +} diff --git a/Zend/tests/bug79793.phpt b/Zend/tests/bug79793.phpt index 5491a2669ed9..4af55ffd07cb 100644 --- a/Zend/tests/bug79793.phpt +++ b/Zend/tests/bug79793.phpt @@ -18,15 +18,15 @@ var_dump($ary); ?> --EXPECT-- -Undefined array key "foobar" array(1) { ["foobar"]=> int(1) } -Undefined array key "foobarbaz" +Undefined array key "foobar" array(2) { ["foobar"]=> int(1) ["foobarbaz"]=> int(1) } +Undefined array key "foobarbaz" diff --git a/Zend/tests/closures/closure_031.phpt b/Zend/tests/closures/closure_031.phpt index 19f3dc6e3212..7f9d3780e4ff 100644 --- a/Zend/tests/closures/closure_031.phpt +++ b/Zend/tests/closures/closure_031.phpt @@ -15,5 +15,5 @@ try { } ?> --EXPECT-- -Warning: Undefined property: Closure::$a NULL +Warning: Undefined property: Closure::$a diff --git a/Zend/tests/compound_assign_failure.phpt b/Zend/tests/compound_assign_failure.phpt index 0dc9af85f253..4ff85da4561c 100644 --- a/Zend/tests/compound_assign_failure.phpt +++ b/Zend/tests/compound_assign_failure.phpt @@ -22,14 +22,16 @@ try { set_error_handler(function($type, $msg) { throw new Exception($msg); }); +function concat(&$a, $b) { $a .= $b; } + try { $a = []; - $a .= "foo"; + concat($a, "foo"); } catch (Throwable $e) { var_dump($a); } try { $a = "foo"; - $a .= []; + concat($a, []); } catch (Throwable $e) { var_dump($a); } $x = new stdClass; @@ -202,9 +204,8 @@ var_dump($x); int(1) int(1) int(1) -array(0) { -} -string(3) "foo" +string(8) "Arrayfoo" +string(8) "fooArray" object(stdClass)#%d (0) { } int(1) diff --git a/Zend/tests/concat/bug81705.phpt b/Zend/tests/concat/bug81705.phpt index 1c00b1c77d4b..10eea6c0a35c 100644 --- a/Zend/tests/concat/bug81705.phpt +++ b/Zend/tests/concat/bug81705.phpt @@ -15,5 +15,5 @@ $my_var .= $GLOBALS["arr"]; var_dump($my_var); ?> --EXPECT-- -error -string(6) "aArray" \ No newline at end of file +string(6) "aArray" +error \ No newline at end of file diff --git a/Zend/tests/dtor_defer/catch_on_early_exit.phpt b/Zend/tests/dtor_defer/catch_on_early_exit.phpt new file mode 100644 index 000000000000..c61950cf5ddc --- /dev/null +++ b/Zend/tests/dtor_defer/catch_on_early_exit.phpt @@ -0,0 +1,57 @@ +--TEST-- +Deferred destructor: a throwing destructor dropped in a try is caught by that try when the try is left via return/break/continue +--FILE-- +id}"); } +} + +function via_return() { + try { + $d = new D("r"); + unset($d); + return "returned"; + } catch (Exception $e) { + echo "return-case caught: {$e->getMessage()}\n"; + return "caught"; + } +} +var_dump(via_return()); + +function via_break() { + foreach ([1] as $v) { + try { + $d = new D("b"); + unset($d); + break; + } catch (Exception $e) { + echo "break-case caught: {$e->getMessage()}\n"; + } + } + return "done"; +} +var_dump(via_break()); + +function via_continue() { + foreach ([1, 2] as $v) { + try { + $d = new D("c$v"); + unset($d); + continue; + } catch (Exception $e) { + echo "continue-case caught: {$e->getMessage()}\n"; + } + } + return "done"; +} +var_dump(via_continue()); +?> +--EXPECT-- +return-case caught: dtor r +string(6) "caught" +break-case caught: dtor b +string(4) "done" +continue-case caught: dtor c1 +continue-case caught: dtor c2 +string(4) "done" diff --git a/Zend/tests/dtor_defer/exit_wins_over_throwing_dtor.phpt b/Zend/tests/dtor_defer/exit_wins_over_throwing_dtor.phpt new file mode 100644 index 000000000000..17a597ad9643 --- /dev/null +++ b/Zend/tests/dtor_defer/exit_wins_over_throwing_dtor.phpt @@ -0,0 +1,36 @@ +--TEST-- +Deferred destructor: exit() in a destructor wins over a throwing destructor in the same flush, either order +--FILE-- +id = $id; } + function __destruct() { + echo "Thrower {$this->id} dtor\n"; + throw new Exception("thrown {$this->id}"); + } +} + +register_shutdown_function(function () { echo "shutdown\n"; }); + +// Thrower deferred before Exiter, then Exiter: exit must win over the pending throw. +$t = new Thrower(1); +$t = null; +$e = new Exiter(); +$e = null; + +// A safepoint flushes the batch. exit(7) wins; no user code runs afterwards. +(function () {})(); + +echo "UNREACHABLE\n"; +?> +--EXPECT-- +Thrower 1 dtor +Exiter dtor +shutdown diff --git a/Zend/tests/dtor_defer/finally_body_dtor_composition.phpt b/Zend/tests/dtor_defer/finally_body_dtor_composition.phpt new file mode 100644 index 000000000000..89d270bb9d58 --- /dev/null +++ b/Zend/tests/dtor_defer/finally_body_dtor_composition.phpt @@ -0,0 +1,32 @@ +--TEST-- +Deferred destructor: a destructor dropped in a finally body composes with a destructor exception pending from the protected block and is caught by the enclosing try +--FILE-- +id}"); } +} +function f() { + try { + try { + $a = new D("try"); + unset($a); + return "unreached"; + } finally { + $b = new D("finally"); + unset($b); + echo "finally body ran\n"; + } + } catch (Exception $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; + echo "previous: ", $e->getPrevious()?->getMessage() ?? "none", "\n"; + return "caught"; + } +} +var_dump(f()); +?> +--EXPECT-- +finally body ran +Exception: dtor finally +previous: dtor try +string(6) "caught" diff --git a/Zend/tests/dtor_defer/finally_throwing_dtor_once.phpt b/Zend/tests/dtor_defer/finally_throwing_dtor_once.phpt new file mode 100644 index 000000000000..9ce2b18899e0 --- /dev/null +++ b/Zend/tests/dtor_defer/finally_throwing_dtor_once.phpt @@ -0,0 +1,30 @@ +--TEST-- +Deferred destructor: a throwing destructor deferred in a finally runs exactly once +--FILE-- + +--EXPECTF-- +dtor + +Fatal error: Uncaught Exception: boom in %s:%d +Stack trace: +#0 %s(%d): D->__destruct() +#1 %s(%d): g() +#2 {main} + thrown in %s on line %d diff --git a/Zend/tests/dtor_defer/gc_condemned_inline.phpt b/Zend/tests/dtor_defer/gc_condemned_inline.phpt new file mode 100644 index 000000000000..9f996bacf662 --- /dev/null +++ b/Zend/tests/dtor_defer/gc_condemned_inline.phpt @@ -0,0 +1,35 @@ +--TEST-- +Deferred destructor: a drop inside a GC destructor of a condemned sibling runs inline +--FILE-- +peer = null; + } +} + +for ($r = 0; $r < 2000; $r++) { + $a = new Node(); + $b = new Node(); + $c = new Node(); + $a->next = $b; + $b->next = $c; + $c->next = $a; + $a->peer = $c; + $b->peer = $a; + $c->peer = $b; + unset($a, $b, $c); + if ($r % 500 === 0) { + gc_collect_cycles(); + } +} +gc_collect_cycles(); +echo "log=$log\n"; +?> +--EXPECT-- +log=6000 diff --git a/Zend/tests/dtor_defer/loop_backedge_flush.phpt b/Zend/tests/dtor_defer/loop_backedge_flush.phpt new file mode 100644 index 000000000000..315d97b9aec3 --- /dev/null +++ b/Zend/tests/dtor_defer/loop_backedge_flush.phpt @@ -0,0 +1,28 @@ +--TEST-- +Deferred destructors flush at loop back-edges +--INI-- +opcache.enable_cli=0 +--FILE-- + +--EXPECT-- +0:0 +1:1 +2:2 +done:2 diff --git a/Zend/tests/dtor_defer/nested_region_scoping.phpt b/Zend/tests/dtor_defer/nested_region_scoping.phpt new file mode 100644 index 000000000000..bafeb9fb3252 --- /dev/null +++ b/Zend/tests/dtor_defer/nested_region_scoping.phpt @@ -0,0 +1,59 @@ +--TEST-- +Deferred destructor: nested try regions scope the deferred queue; each region's destructor surfaces at its own level and a finally-return discards only its own +--FILE-- +id}"); } +} + +function inner_level() { + try { + try { + $d = new D("inner"); + unset($d); + return "inner-try-return"; + } catch (Exception $e) { + echo "inner caught: {$e->getMessage()}\n"; + return "inner-catch"; + } + } catch (Exception $e) { + echo "outer WRONGLY caught: {$e->getMessage()}\n"; + return "outer-catch"; + } +} +var_dump(inner_level()); + +function outer_survives() { + try { + $d = new D("outer"); + unset($d); + try { + return "inner-try-return"; + } finally { + return "inner-finally-return"; + } + } catch (Exception $e) { + echo "outer caught: {$e->getMessage()}\n"; + return "outer-catch"; + } +} +var_dump(outer_survives()); + +function finally_discards() { + try { + $d = new D("discarded"); + unset($d); + return "try-return"; + } finally { + return "finally-return"; + } +} +var_dump(finally_discards()); +?> +--EXPECT-- +inner caught: dtor inner +string(11) "inner-catch" +outer caught: dtor outer +string(11) "outer-catch" +string(14) "finally-return" diff --git a/Zend/tests/dtor_defer/throw_after_deferred_dtor.phpt b/Zend/tests/dtor_defer/throw_after_deferred_dtor.phpt new file mode 100644 index 000000000000..34f7cf9b74e9 --- /dev/null +++ b/Zend/tests/dtor_defer/throw_after_deferred_dtor.phpt @@ -0,0 +1,43 @@ +--TEST-- +Deferred destructor: a throwing destructor pending at an explicit throw preempts it, whether dropped before the statement or during the throw operand's evaluation, so no spurious exception chain is created +--FILE-- +getMessage(), " prev=", $e->getPrevious()?->getMessage() ?? "none", "\n"; + } +} +rethrow_case(); + +// The throw operand is a call that drops the destructor during its evaluation. +function make(Exception $e) { + $x = new D(); + unset($x); + return $e; +} +function operand_call_case() { + $pre = new Exception("explicit"); + try { + throw make($pre); + } catch (Exception $e) { + echo "operand-call: ", $e->getMessage(), " prev=", $e->getPrevious()?->getMessage() ?? "none", "\n"; + } +} +operand_call_case(); +?> +--EXPECT-- +rethrow: dtor prev=none +operand-call: dtor prev=none diff --git a/Zend/tests/dtor_defer/throw_preempt_uncatchable.phpt b/Zend/tests/dtor_defer/throw_preempt_uncatchable.phpt new file mode 100644 index 000000000000..f2e2cf876739 --- /dev/null +++ b/Zend/tests/dtor_defer/throw_preempt_uncatchable.phpt @@ -0,0 +1,18 @@ +--TEST-- +Deferred destructor: an uncatchable throwing destructor pending at an explicit throw or internal call preempts it positionally instead of being held to shutdown +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception: dtor in %s:%d +Stack trace: +#0 %s(%d): D->__destruct() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/dtor_defer/weakmap_dead_key_absent.phpt b/Zend/tests/dtor_defer/weakmap_dead_key_absent.phpt new file mode 100644 index 000000000000..17e9e478df8b --- /dev/null +++ b/Zend/tests/dtor_defer/weakmap_dead_key_absent.phpt @@ -0,0 +1,18 @@ +--TEST-- +Deferred destructor: a dying WeakMap key leaves the map at logical death +--FILE-- + +--EXPECT-- +before: 2 +after unset k1: 1 +end diff --git a/Zend/tests/dtor_defer/weakref_no_resurrection.phpt b/Zend/tests/dtor_defer/weakref_no_resurrection.phpt new file mode 100644 index 000000000000..bb3806161ace --- /dev/null +++ b/Zend/tests/dtor_defer/weakref_no_resurrection.phpt @@ -0,0 +1,21 @@ +--TEST-- +Deferred destructor: a WeakReference to the dying object returns null immediately +--FILE-- +get(); +echo $v === null ? "null\n" : "live\n"; +echo "end\n"; +?> +--EXPECT-- +null +end +dtor diff --git a/Zend/tests/dynamic_prop_deprecation_002.phpt b/Zend/tests/dynamic_prop_deprecation_002.phpt index bd0d3aa5a7df..20182d2a8923 100644 --- a/Zend/tests/dynamic_prop_deprecation_002.phpt +++ b/Zend/tests/dynamic_prop_deprecation_002.phpt @@ -15,4 +15,3 @@ try { ?> --EXPECT-- Err: Creation of dynamic property class@anonymous::$y is deprecated -Exception: Cannot create dynamic property class@anonymous::$y diff --git a/Zend/tests/ex_func_null_during_property_write.phpt b/Zend/tests/ex_func_null_during_property_write.phpt index 6a253f760e0b..05c01dad4059 100644 --- a/Zend/tests/ex_func_null_during_property_write.phpt +++ b/Zend/tests/ex_func_null_during_property_write.phpt @@ -15,11 +15,11 @@ new a; --EXPECTF-- Fatal error: Uncaught Error: Object of class a could not be converted to string in %s:%d Stack trace: -#0 %s(%d): a->__destruct() +#0 [internal function]: a->__destruct() #1 {main} Next Exception in %s:%d Stack trace: -#0 %s(%d): a->__destruct() +#0 [internal function]: a->__destruct() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/exception_in_nested_rope.phpt b/Zend/tests/exception_in_nested_rope.phpt index 7afd1412354a..27cfe6d77168 100644 --- a/Zend/tests/exception_in_nested_rope.phpt +++ b/Zend/tests/exception_in_nested_rope.phpt @@ -15,4 +15,9 @@ try { ?> --EXPECTF-- Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d -Exception + +Fatal error: Uncaught Exception in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(2, 'Undefined varia...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/exception_in_rope_end.phpt b/Zend/tests/exception_in_rope_end.phpt index 3e6402c60f42..da6fa6a61903 100644 --- a/Zend/tests/exception_in_rope_end.phpt +++ b/Zend/tests/exception_in_rope_end.phpt @@ -13,5 +13,9 @@ try { } ?> ---EXPECT-- -Exception +--EXPECTF-- +Fatal error: Uncaught Exception in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(2, 'Undefined varia...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/exceptions/bug53511.phpt b/Zend/tests/exceptions/bug53511.phpt index b07504506a94..c3a7d90e0449 100644 --- a/Zend/tests/exceptions/bug53511.phpt +++ b/Zend/tests/exceptions/bug53511.phpt @@ -21,9 +21,11 @@ test(); echo "bug\n"; ?> --EXPECTF-- -Fatal error: Uncaught Exception: ops 1 in %sbug53511.php:4 +ops 2 +bug + +Fatal error: Uncaught Exception: ops 1 in %sbug53511.php:%d Stack trace: -#0 %sbug53511.php(12): Foo->__destruct() -#1 %sbug53511.php(17): test() -#2 {main} - thrown in %sbug53511.php on line 4 +#0 %s: Foo->__destruct() +#1 {main} + thrown in %sbug53511.php on line %d diff --git a/Zend/tests/exceptions/exception_008.phpt b/Zend/tests/exceptions/exception_008.phpt index 4640ec965ad5..3877fda928d3 100644 --- a/Zend/tests/exceptions/exception_008.phpt +++ b/Zend/tests/exceptions/exception_008.phpt @@ -24,13 +24,15 @@ unset($ar); ?> ===DONE=== --EXPECTF-- +===DONE=== + Fatal error: Uncaught Exception: First in %sexception_008.php:%d Stack trace: -#0 %sexception_008.php(%d): TestFirst->__destruct() +#0 [internal function]: TestFirst->__destruct() #1 {main} Next Exception: Second in %sexception_008.php:%d Stack trace: -#0 %sexception_008.php(%d): TestSecond->__destruct() +#0 [internal function]: TestSecond->__destruct() #1 {main} thrown in %sexception_008.php on line %d diff --git a/Zend/tests/exceptions/exception_026.phpt b/Zend/tests/exceptions/exception_026.phpt index 0c47a449a4bf..1994545f571c 100644 --- a/Zend/tests/exceptions/exception_026.phpt +++ b/Zend/tests/exceptions/exception_026.phpt @@ -16,11 +16,11 @@ new A; --EXPECTF-- Fatal error: Uncaught Error: Undefined constant "Y" in %s:8 Stack trace: -#0 %s(11): A->__destruct() +#0 [internal function]: A->__destruct() #1 {main} Next Error: Undefined constant "X" in %s:6 Stack trace: -#0 %s(11): A->__destruct() +#0 [internal function]: A->__destruct() #1 {main} thrown in %s on line 6 diff --git a/Zend/tests/exceptions/exception_before_fatal.phpt b/Zend/tests/exceptions/exception_before_fatal.phpt index edc63b2394cd..847cc2cd8f96 100644 --- a/Zend/tests/exceptions/exception_before_fatal.phpt +++ b/Zend/tests/exceptions/exception_before_fatal.phpt @@ -61,4 +61,4 @@ string(23) "Undefined variable $foo" string(23) "Undefined variable $foo" string(23) "Undefined variable $foo" string(23) "Undefined variable $foo" -string(23) "Undefined variable $foo" +string(23) "Undefined variable $foo" \ No newline at end of file diff --git a/Zend/tests/falsetoarray_002.phpt b/Zend/tests/falsetoarray_002.phpt index c01b79954596..639cd51b3661 100644 --- a/Zend/tests/falsetoarray_002.phpt +++ b/Zend/tests/falsetoarray_002.phpt @@ -11,5 +11,13 @@ $a[0][$d]='b'; var_dump($a); ?> --EXPECT-- +array(1) { + [0]=> + array(1) { + [""]=> + string(1) "b" + } +} Err: Automatic conversion of false to array is deprecated -string(0) "" +Err: Undefined variable $d +Err: Using null as an array offset is deprecated, use an empty string instead diff --git a/Zend/tests/falsetoarray_003.phpt b/Zend/tests/falsetoarray_003.phpt index 117e443ef958..d62dff41941c 100644 --- a/Zend/tests/falsetoarray_003.phpt +++ b/Zend/tests/falsetoarray_003.phpt @@ -11,6 +11,6 @@ $a=[]; ?> DONE --EXPECTF-- +DONE Err: The float %f is not representable as an int, cast occurred Err: Undefined array key %i -DONE diff --git a/Zend/tests/fibers/unfinished-fiber-with-finally.phpt b/Zend/tests/fibers/unfinished-fiber-with-finally.phpt index 84ba74e646c6..b0a5649adb81 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-finally.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-finally.phpt @@ -26,5 +26,5 @@ echo "done\n"; ?> --EXPECT-- fiber -finally done +finally diff --git a/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt b/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt index 664e4a052b8f..e8c881e30c66 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt @@ -42,6 +42,6 @@ echo "done\n"; ?> --EXPECT-- fiber +done inner finally outer finally -done diff --git a/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt b/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt index e38774df82bf..93eb00833ae7 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt @@ -32,5 +32,5 @@ echo "done\n"; --EXPECT-- fiber inner finally -outer finally done +outer finally diff --git a/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt b/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt index f1b17caeb5d7..567034be0a4a 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt @@ -41,8 +41,8 @@ echo "done\n"; ?> --EXPECT-- fiber +done inner finally finally exception outer finally Cannot suspend in a force-closed fiber -done diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt index 97831a8d65f0..51c22102bddd 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt @@ -28,4 +28,13 @@ try { ?> --EXPECT-- +object(Closure)#2 (2) { + ["function"]=> + string(13) "Foo::myMethod" + ["parameter"]=> + array(1) { + ["$foo"]=> + string(10) "" + } +} Caught: Calling static trait method Foo::myMethod is deprecated, it should only be called on a class using the trait diff --git a/Zend/tests/frameless_throwing_destructor.phpt b/Zend/tests/frameless_throwing_destructor.phpt index ad555d860e66..28bb6caf4ba4 100644 --- a/Zend/tests/frameless_throwing_destructor.phpt +++ b/Zend/tests/frameless_throwing_destructor.phpt @@ -13,6 +13,6 @@ in_array(new Foo(), [new Bar()], true); --EXPECTF-- Fatal error: Uncaught Exception in %s:%d Stack trace: -#0 %s(%d): Bar->__destruct() +#0 [internal function]: Bar->__destruct() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/function_arguments/sensitive_parameter_value_keeps_object_alive.phpt b/Zend/tests/function_arguments/sensitive_parameter_value_keeps_object_alive.phpt index e7b0de51b969..d4deb4e51294 100644 --- a/Zend/tests/function_arguments/sensitive_parameter_value_keeps_object_alive.phpt +++ b/Zend/tests/function_arguments/sensitive_parameter_value_keeps_object_alive.phpt @@ -70,5 +70,5 @@ CustomDestructor::__construct - 2 catch int(2) Before unset -CustomDestructor::__destruct - 2 After unset +CustomDestructor::__destruct - 2 diff --git a/Zend/tests/gc_053.phpt b/Zend/tests/gc_053.phpt index 858be7cbebd5..920609600e3d 100644 --- a/Zend/tests/gc_053.phpt +++ b/Zend/tests/gc_053.phpt @@ -23,15 +23,15 @@ $weakO = \WeakReference::create($o); echo "---\n"; unset($o); echo "---\n"; -var_dump($weakO->get() !== null); // verify if kept allocated +var_dump($weakO->get() !== null); // weakref severed at the drop; the deferred dtor re-referencing $this does not restore it G::$v = null; echo "---\n"; -var_dump($weakO->get() !== null); // verify if released +var_dump($weakO->get() !== null); // still severed ?> --EXPECT-- --- -d --- -bool(true) +d +bool(false) --- bool(false) diff --git a/Zend/tests/generators/bug71601.phpt b/Zend/tests/generators/bug71601.phpt index c8e226329dfe..a4a156e5ae3c 100644 --- a/Zend/tests/generators/bug71601.phpt +++ b/Zend/tests/generators/bug71601.phpt @@ -34,6 +34,6 @@ echo "Done\n"; --EXPECT-- Entered try/catch int(1) +Done Inner finally Finally -Done diff --git a/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt index af84e50215ce..894a4d7e8e4b 100644 --- a/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt +++ b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt @@ -28,6 +28,6 @@ before yield in finally Fatal error: Uncaught Error: Cannot yield from finally in a force-closed generator in %s:%d Stack trace: -#0 %s(%d): gen() +#0 [internal function]: gen() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/generators/generator_closure_collection.phpt b/Zend/tests/generators/generator_closure_collection.phpt index 7386adeb80c5..0721c0bf8979 100644 --- a/Zend/tests/generators/generator_closure_collection.phpt +++ b/Zend/tests/generators/generator_closure_collection.phpt @@ -21,6 +21,8 @@ var_dump($r->get()); unset($generator); +(function () {})(); + var_dump($r->get()); ?> diff --git a/Zend/tests/generators/generator_deferred_dtor_caught_in_generator.phpt b/Zend/tests/generators/generator_deferred_dtor_caught_in_generator.phpt new file mode 100644 index 000000000000..803c069f7993 --- /dev/null +++ b/Zend/tests/generators/generator_deferred_dtor_caught_in_generator.phpt @@ -0,0 +1,58 @@ +--TEST-- +A deferred destructor dropped in a generator is caught by that generator, not the consumer +--FILE-- +id}"); } +} + +function gen() { + try { + $d = new D(1); + unset($d); + yield 1; + yield 2; + } catch (Exception $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; + } +} + +try { + foreach (gen() as $v) { + echo "consumer got $v\n"; + } + echo "consumer done\n"; +} catch (Exception $e) { + echo "ESCAPED to consumer: ", $e->getMessage(), "\n"; +} + +function inner() { + try { + $d = new D(2); + unset($d); + yield 1; + } catch (Exception $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; + } + yield 3; +} +function outer() { yield from inner(); } + +try { + foreach (outer() as $v) { + echo "outer got $v\n"; + } + echo "outer done\n"; +} catch (Exception $e) { + echo "ESCAPED to outer consumer: ", $e->getMessage(), "\n"; +} +echo "end\n"; +?> +--EXPECT-- +Exception: dtor 1 +consumer done +Exception: dtor 2 +outer got 3 +outer done +end diff --git a/Zend/tests/get_class_basic.phpt b/Zend/tests/get_class_basic.phpt index f6dcbccb6916..d8809ba9d9cf 100644 --- a/Zend/tests/get_class_basic.phpt +++ b/Zend/tests/get_class_basic.phpt @@ -54,6 +54,7 @@ $f1->testNull(); echo "Done\n"; ?> --EXPECTF-- +string(3) "foo" Calling get_class() without arguments is deprecated Deprecated: Calling get_class() without arguments is deprecated in %s on line %d diff --git a/Zend/tests/gh10168/assign_prop_ref.phpt b/Zend/tests/gh10168/assign_prop_ref.phpt index 606542fbd6c6..6e56a863a1ff 100644 --- a/Zend/tests/gh10168/assign_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_prop_ref.phpt @@ -27,6 +27,7 @@ test($box); ?> --EXPECT-- -NULL -object(Test)#2 (0) { +object(Test)#3 (0) { +} +object(Test)#3 (0) { } diff --git a/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt index f887acbc1d06..737754b67125 100644 --- a/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt @@ -32,4 +32,5 @@ test($box); --EXPECT-- object(Test)#3 (0) { } -NULL +object(Test)#4 (0) { +} diff --git a/Zend/tests/gh10168/assign_ref.phpt b/Zend/tests/gh10168/assign_ref.phpt index 9f3be5619d1a..a05c26700bcf 100644 --- a/Zend/tests/gh10168/assign_ref.phpt +++ b/Zend/tests/gh10168/assign_ref.phpt @@ -15,4 +15,5 @@ var_dump($a = &$tmp); ?> --EXPECT-- -NULL +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt index 42ce94b3f83e..8afc098294ba 100644 --- a/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt @@ -17,4 +17,5 @@ var_dump($a = &$tmp); ?> --EXPECT-- -NULL +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_static_prop_ref.phpt b/Zend/tests/gh10168/assign_static_prop_ref.phpt index 2e90be884ded..582d1f03da46 100644 --- a/Zend/tests/gh10168/assign_static_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_static_prop_ref.phpt @@ -17,4 +17,5 @@ var_dump(Test::$test = &$tmp); ?> --EXPECT-- -NULL +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt b/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt index dfef8ead26f6..2d3679edc36d 100644 --- a/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt @@ -17,4 +17,5 @@ var_dump(Test::$test = &$tmp); ?> --EXPECT-- -NULL +object(Test)#2 (0) { +} diff --git a/Zend/tests/gh10168/assign_untyped_prop_ref.phpt b/Zend/tests/gh10168/assign_untyped_prop_ref.phpt index a28395d43bbb..1f09f0662bd2 100644 --- a/Zend/tests/gh10168/assign_untyped_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_untyped_prop_ref.phpt @@ -27,6 +27,7 @@ test($box); ?> --EXPECT-- -NULL -object(Test)#2 (0) { +object(Test)#3 (0) { +} +object(Test)#3 (0) { } diff --git a/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt index 79ff5fefc07e..b0889ad832e0 100644 --- a/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt @@ -32,4 +32,5 @@ test($box); --EXPECT-- object(Test)#3 (0) { } -NULL +object(Test)#4 (0) { +} diff --git a/Zend/tests/gh16792.phpt b/Zend/tests/gh16792.phpt new file mode 100644 index 000000000000..ed2eae538d3d --- /dev/null +++ b/Zend/tests/gh16792.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-16792 (Assertion failure when an error handler mutates $GLOBALS during a by-ref sort) +--FILE-- + +--EXPECT-- +ok diff --git a/Zend/tests/gh17416.phpt b/Zend/tests/gh17416.phpt new file mode 100644 index 000000000000..1fd0e7d5ce04 --- /dev/null +++ b/Zend/tests/gh17416.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-17416 (Assertion failure when a throwing error handler runs while an array is unset during foreach) +--FILE-- + $val) { + if ($val === 2) { + unset($a[$fusion]); + } + } +} +function foo($a, bool $b): bool { + do { + $res = bar($a); + } while ($res === null && $n !== $n2); +} +foo([2, 'a' => 5], false); +?> +--EXPECTF-- +Fatal error: Uncaught Exception: Undefined variable $fusion in %s:%d +Stack trace: +#0 %s(%d): Error2Exception(2, 'Undefined varia...', '%s', %d) +#1 %s(%d): bar(Array) +#2 %s(%d): foo(Array, false) +#3 {main} + thrown in %s on line %d diff --git a/Zend/tests/gh21245.phpt b/Zend/tests/gh21245.phpt new file mode 100644 index 000000000000..c922b3865c3c --- /dev/null +++ b/Zend/tests/gh21245.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-21245 (Use-after-free in ASSIGN_DIM when the error handler grows the array holding a typed-property reference) +--FILE-- +x = ""; +$a[0] =& $test->x; +var_dump($a[0] = $v); +?> +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot assign null to reference held by property Test::$x of type string in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/gh22419.phpt b/Zend/tests/gh22419.phpt new file mode 100644 index 000000000000..f6e3241801d3 --- /dev/null +++ b/Zend/tests/gh22419.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-22419 (UAF/refcount assertion in array-offset concat when the error handler replaces the LHS) +--FILE-- + +--EXPECT-- +ok diff --git a/Zend/tests/in-de-crement/incdec_bool_exception.phpt b/Zend/tests/in-de-crement/incdec_bool_exception.phpt index f819af1e2395..d7ccf55e406f 100644 --- a/Zend/tests/in-de-crement/incdec_bool_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_bool_exception.phpt @@ -7,15 +7,22 @@ set_error_handler(function($severity, $m) { throw new Exception($m, $severity); }); +function inc(&$v) { + $v++; +} +function dec(&$v) { + $v--; +} + $values = [false, true]; foreach ($values as $value) { try { - $value++; + inc($value); } catch (\Exception $e) { echo $e->getMessage(), PHP_EOL; } try { - $value--; + dec($value); } catch (\Exception $e) { echo $e->getMessage(), PHP_EOL; } diff --git a/Zend/tests/in-de-crement/incdec_strings_exception.phpt b/Zend/tests/in-de-crement/incdec_strings_exception.phpt index 5acbb1041222..b5b00e6c00d6 100644 --- a/Zend/tests/in-de-crement/incdec_strings_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_strings_exception.phpt @@ -13,6 +13,13 @@ set_error_handler(function($severity, $m) { throw new Exception($m, $severity); }); +function inc(&$v) { + $v++; +} +function dec(&$v) { + $v--; +} + $values = [ '', ' ', @@ -26,47 +33,49 @@ $values = [ '🐘' ]; foreach ($values as $value) { + $v = $value; try { - $value++; + inc($v); } catch (\Exception $e) { echo $e->getMessage(), PHP_EOL; } - var_dump($value); + var_dump($v); + $v = $value; try { - $value--; + dec($v); } catch (\Exception $e) { echo $e->getMessage(), PHP_EOL; } - var_dump($value); + var_dump($v); } ?> --EXPECT-- Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead -string(0) "" +string(1) "1" Deprecated: Decrement on empty string is deprecated as non-numeric -string(0) "" +int(-1) Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead string(1) " " Deprecated: Decrement on non-numeric string has no effect and is deprecated string(1) " " Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead -string(4) "199A" +string(4) "199B" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "199A" Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead -string(4) "A199" +string(4) "A200" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "A199" Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead -string(4) "199Z" +string(4) "200A" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "199Z" Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead -string(4) "Z199" +string(4) "Z200" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "Z199" Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead -string(11) "Hello world" +string(11) "Hello worle" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(11) "Hello world" Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead diff --git a/Zend/tests/in-de-crement/incdec_undef.phpt b/Zend/tests/in-de-crement/incdec_undef.phpt index db560e31c99f..549c64fea87e 100644 --- a/Zend/tests/in-de-crement/incdec_undef.phpt +++ b/Zend/tests/in-de-crement/incdec_undef.phpt @@ -14,6 +14,7 @@ unset($x); var_dump(++$x); ?> --EXPECT-- +NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP NULL @@ -21,6 +22,5 @@ Undefined variable $x NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP -NULL -Undefined variable $x int(1) +Undefined variable $x diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt index 11a0edac1917..b55c8c6b811e 100644 --- a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt @@ -31,8 +31,8 @@ var_dump($x); DONE --EXPECT-- string(1) "1" -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) "foo!" string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "!" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" DONE diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt index 8e63ad6aeed4..9308a1a7bd3d 100644 --- a/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt @@ -23,8 +23,8 @@ var_dump($x); ?> DONE --EXPECT-- -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) "foo!" string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "!" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" DONE diff --git a/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt b/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt index e981800eeac1..1f1fc7228134 100644 --- a/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt +++ b/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt @@ -21,16 +21,16 @@ var_dump(++$x); ?> --EXPECT-- POST DEC +NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP -NULL POST INC -Undefined variable $x NULL +Undefined variable $x PRE DEC +NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP -NULL PRE INC -Undefined variable $x int(1) +Undefined variable $x diff --git a/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt b/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt index f52dff52e631..e39184e68154 100644 --- a/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt +++ b/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt @@ -25,14 +25,14 @@ var_dump(++$x); ?> --EXPECT-- POST DEC -Decrement on non-numeric string has no effect and is deprecated string(1) " " -PRE DEC Decrement on non-numeric string has no effect and is deprecated +PRE DEC string(1) " " +Decrement on non-numeric string has no effect and is deprecated POST INC -Increment on non-numeric string is deprecated, use str_increment() instead string(1) " " -PRE INC Increment on non-numeric string is deprecated, use str_increment() instead +PRE INC string(1) " " +Increment on non-numeric string is deprecated, use str_increment() instead diff --git a/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt index 31ffea22467b..88302517ce05 100644 --- a/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt @@ -78,53 +78,53 @@ unset($x); --EXPECT-- NULL (only --) POST DEC -Decrement on type null has no effect, this will change in the next major version of PHP NULL -PRE DEC Decrement on type null has no effect, this will change in the next major version of PHP +PRE DEC NULL +Decrement on type null has no effect, this will change in the next major version of PHP Empty string POST INC -Increment on non-numeric string is deprecated, use str_increment() instead string(0) "" +Increment on non-numeric string is deprecated, use str_increment() instead POST DEC -Decrement on empty string is deprecated as non-numeric string(0) "" +Decrement on empty string is deprecated as non-numeric PRE INC -Increment on non-numeric string is deprecated, use str_increment() instead string(1) "1" +Increment on non-numeric string is deprecated, use str_increment() instead PRE DEC -Decrement on empty string is deprecated as non-numeric int(-1) +Decrement on empty string is deprecated as non-numeric Non fill ASCII (only ++) POST INC -Increment on non-numeric string is deprecated, use str_increment() instead string(4) " ad " -PRE INC Increment on non-numeric string is deprecated, use str_increment() instead +PRE INC string(4) " ad " +Increment on non-numeric string is deprecated, use str_increment() instead Bool POST INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(false) +Increment on type bool has no effect, this will change in the next major version of PHP POST DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(false) +Decrement on type bool has no effect, this will change in the next major version of PHP PRE INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(false) +Increment on type bool has no effect, this will change in the next major version of PHP PRE DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(false) +Decrement on type bool has no effect, this will change in the next major version of PHP POST INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(true) +Increment on type bool has no effect, this will change in the next major version of PHP POST DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(true) +Decrement on type bool has no effect, this will change in the next major version of PHP PRE INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(true) +Increment on type bool has no effect, this will change in the next major version of PHP PRE DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(true) +Decrement on type bool has no effect, this will change in the next major version of PHP diff --git a/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt index 4d2a4705588a..b00ba707cecf 100644 --- a/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt @@ -87,57 +87,57 @@ var_dump(--$c->a); unset($c->a); ?> --EXPECT-- -string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" NULL +string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" NULL (only --) POST DEC -string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" NULL -PRE DEC string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" +PRE DEC NULL +string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" Empty string POST INC -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(0) "" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" POST DEC -string(54) "Decrement on empty string is deprecated as non-numeric" string(0) "" +string(54) "Decrement on empty string is deprecated as non-numeric" PRE INC -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "1" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" PRE DEC -string(54) "Decrement on empty string is deprecated as non-numeric" int(-1) +string(54) "Decrement on empty string is deprecated as non-numeric" Non fill ASCII (only ++) POST INC -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) " ad " -PRE INC string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" +PRE INC string(4) " ad " +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" Bool POST INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" POST DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" PRE INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" PRE DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" POST INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" POST DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" PRE INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" PRE DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" diff --git a/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt index d435c9fb4029..55d3283ead91 100644 --- a/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt @@ -20,6 +20,5 @@ try { var_dump($c->a); ?> --EXPECT-- -Cannot increment stdClass object(stdClass)#2 (0) { } diff --git a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt index 7a59cca70bd6..77020277f3b8 100644 --- a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt +++ b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt @@ -24,7 +24,7 @@ var_dump(new C()); ?> --EXPECTF-- -Exception: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice +Exception: Return type of C::getTimestamp() should either be compatible with DateTime::getTimestamp(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice object(C)#%d (3) { ["date"]=> string(%d) "%s" @@ -32,4 +32,4 @@ object(C)#%d (3) { int(3) ["timezone"]=> string(3) "UTC" -} +} \ No newline at end of file diff --git a/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt b/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt index 733da55a5cbc..cf94e4f1a134 100644 --- a/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt +++ b/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt @@ -51,8 +51,8 @@ string(13) "C::__destruct" After makeLazy string(11) "initializer" int(1) -string(13) "C::__destruct" # Proxy: +string(13) "C::__destruct" In makeLazy string(13) "C::__destruct" After makeLazy diff --git a/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt b/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt index d0c22a0333ff..e45fbe7f8b29 100644 --- a/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt +++ b/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt @@ -50,8 +50,8 @@ In makeLazy After makeLazy string(11) "initializer" int(1) -string(13) "C::__destruct" # Proxy: +string(13) "C::__destruct" In makeLazy After makeLazy string(11) "initializer" diff --git a/Zend/tests/magic_methods/bug32596.phpt b/Zend/tests/magic_methods/bug32596.phpt index 40bd70382b30..ae22c82f4772 100644 --- a/Zend/tests/magic_methods/bug32596.phpt +++ b/Zend/tests/magic_methods/bug32596.phpt @@ -21,6 +21,6 @@ BUG::instance()->error; echo "this is still executed\n"; ?> --EXPECT-- +this is still executed BUG please fix this thing, it wasted a nice part of my life! -this is still executed diff --git a/Zend/tests/offsets/array_offset_002.phpt b/Zend/tests/offsets/array_offset_002.phpt index 4d56258ef8b8..ece8a53c7215 100644 --- a/Zend/tests/offsets/array_offset_002.phpt +++ b/Zend/tests/offsets/array_offset_002.phpt @@ -12,7 +12,9 @@ function x(&$s){ x($y); var_dump($y); ?> ---EXPECT-- +--EXPECTF-- Err: The float 1.0E+20 is not representable as an int, cast occurred -array(0) { +array(1) { + [%d]=> + int(1) } diff --git a/Zend/tests/offsets/null_offset_dep_promoted.phpt b/Zend/tests/offsets/null_offset_dep_promoted.phpt index c26095d4f745..55145c88837a 100644 --- a/Zend/tests/offsets/null_offset_dep_promoted.phpt +++ b/Zend/tests/offsets/null_offset_dep_promoted.phpt @@ -13,5 +13,9 @@ try { echo $e::class, ': ', $e->getMessage(), PHP_EOL; } ?> ---EXPECT-- -Exception: Using null as an array offset is deprecated, use an empty string instead +--EXPECTF-- +Fatal error: Uncaught Exception: Using null as an array offset is deprecated, use an empty string instead in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(%d, 'Using null as a...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/offsets/null_offset_no_uaf.phpt b/Zend/tests/offsets/null_offset_no_uaf.phpt index 38a1b9868345..3352438688fc 100644 --- a/Zend/tests/offsets/null_offset_no_uaf.phpt +++ b/Zend/tests/offsets/null_offset_no_uaf.phpt @@ -13,5 +13,5 @@ $ary[null] = 1; echo "\nSuccess\n"; ?> --EXPECTF-- -Using null as an array offset is deprecated, use an empty string instead Success +Using null as an array offset is deprecated, use an empty string instead diff --git a/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt b/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt index cfaa2b3b20d9..1dd363bab30b 100644 --- a/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt +++ b/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt @@ -14,6 +14,5 @@ $b = [0, null => $a]; echo "\nSuccess\n"; ?> --EXPECTF-- -string(72) "Using null as an array offset is deprecated, use an empty string instead" - Success +string(72) "Using null as an array offset is deprecated, use an empty string instead" diff --git a/Zend/tests/operator_unsupported_types.phpt b/Zend/tests/operator_unsupported_types.phpt index 904ac402b372..1f85bfee871e 100644 --- a/Zend/tests/operator_unsupported_types.phpt +++ b/Zend/tests/operator_unsupported_types.phpt @@ -2104,7 +2104,7 @@ Cannot increment stdClass Cannot decrement stdClass Cannot increment resource Cannot decrement resource -Warning: Increment on non-numeric string is deprecated, use str_increment() instead No error for fop++ -Warning: Decrement on non-numeric string has no effect and is deprecated +Warning: Increment on non-numeric string is deprecated, use str_increment() instead No error for foo-- +Warning: Decrement on non-numeric string has no effect and is deprecated \ No newline at end of file diff --git a/Zend/tests/oss_fuzz_456317305.phpt b/Zend/tests/oss_fuzz_456317305.phpt index 37e7c59e4651..c0e3a1d70c95 100644 --- a/Zend/tests/oss_fuzz_456317305.phpt +++ b/Zend/tests/oss_fuzz_456317305.phpt @@ -21,5 +21,10 @@ $c = new C; Fatal error: Uncaught Exception in %s:%d Stack trace: #0 [internal function]: C->__destruct() +#1 {main} + +Next Exception in %s:%d +Stack trace: +#0 [internal function]: C->__destruct() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/oss_fuzz_54325.phpt b/Zend/tests/oss_fuzz_54325.phpt index d998acf1ffed..18b108681c2d 100644 --- a/Zend/tests/oss_fuzz_54325.phpt +++ b/Zend/tests/oss_fuzz_54325.phpt @@ -14,6 +14,5 @@ $$x++; var_dump($x); ?> --EXPECT-- +string(3) "oof" string(23) "Undefined variable $oof" -object(stdClass)#2 (0) { -} diff --git a/Zend/tests/oss_fuzz_61712.phpt b/Zend/tests/oss_fuzz_61712.phpt index 5e3aa9060fde..655fb56c1421 100644 --- a/Zend/tests/oss_fuzz_61712.phpt +++ b/Zend/tests/oss_fuzz_61712.phpt @@ -16,5 +16,5 @@ $c->a %= 10; var_dump($c->a); ?> --EXPECT-- -Undefined property: C::$a int(0) +Undefined property: C::$a diff --git a/Zend/tests/oss_fuzz_61712b.phpt b/Zend/tests/oss_fuzz_61712b.phpt index 8ee93b97b432..bfb3d2757366 100644 --- a/Zend/tests/oss_fuzz_61712b.phpt +++ b/Zend/tests/oss_fuzz_61712b.phpt @@ -16,5 +16,5 @@ $c->a %= 10; var_dump($c->a); ?> --EXPECT-- +int(0) Undefined property: C::$a -int(5) diff --git a/Zend/tests/stack_limit/gh16041_001.phpt b/Zend/tests/stack_limit/gh16041_001.phpt index 4d3e41a54dcd..4a9a369354f8 100644 --- a/Zend/tests/stack_limit/gh16041_001.phpt +++ b/Zend/tests/stack_limit/gh16041_001.phpt @@ -27,13 +27,6 @@ new Canary(); ?> --EXPECTF-- [Successful compilation of %sgh16041_001.php] -prompt> prompt> [Uncaught Error in %s on line %d: Maximum call stack size of %d bytes%s ->00005: new Canary(); - 00006: } - 00007: } -prompt> [Uncaught Error in %s on line %d] -Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? in %s:%d -Stack trace: -#0 %s(%d): Canary->__destruct() -%a +prompt> prompt> [Script ended normally] +prompt> [Not running] prompt> diff --git a/Zend/tests/str_offset_006.phpt b/Zend/tests/str_offset_006.phpt index 3cdf91656bd2..01325defe954 100644 --- a/Zend/tests/str_offset_006.phpt +++ b/Zend/tests/str_offset_006.phpt @@ -9,8 +9,13 @@ set_error_handler(function($code, $msg) { $a[$y]=$a.=($y); var_dump($a); ?> ---EXPECT-- +--EXPECTF-- Err: Undefined variable $y +Err: Undefined variable $a Err: Undefined variable $y Err: String offset cast occurred -NULL + +Fatal error: Uncaught Error: Cannot assign an empty string to a string offset in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d \ No newline at end of file diff --git a/Zend/tests/str_offset_007.phpt b/Zend/tests/str_offset_007.phpt index 3998ac401f63..09d254cac3bf 100644 --- a/Zend/tests/str_offset_007.phpt +++ b/Zend/tests/str_offset_007.phpt @@ -11,6 +11,9 @@ $a[0][$d]='b'; var_dump($a); ?> --EXPECT-- +array(1) { + [0]=> + string(1) "b" +} Err: Undefined variable $d Err: String offset cast occurred -string(0) "" diff --git a/Zend/tests/str_offset_008.phpt b/Zend/tests/str_offset_008.phpt index e99e46e59e74..7a88136d5298 100644 --- a/Zend/tests/str_offset_008.phpt +++ b/Zend/tests/str_offset_008.phpt @@ -12,7 +12,7 @@ var_dump($a[0][$b]); var_dump($a); ?> --EXPECT-- +string(1) "x" Err: Undefined variable $b Err: String offset cast occurred -string(1) "x" int(8) diff --git a/Zend/tests/strlen_deprecation_to_exception.phpt b/Zend/tests/strlen_deprecation_to_exception.phpt index 7b616f3b6432..48cba977a06a 100644 --- a/Zend/tests/strlen_deprecation_to_exception.phpt +++ b/Zend/tests/strlen_deprecation_to_exception.phpt @@ -13,5 +13,9 @@ try { } ?> ---EXPECT-- -strlen(): Passing null to parameter #1 ($string) of type string is deprecated +--EXPECTF-- +Fatal error: Uncaught Exception: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(%s) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt b/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt index f5e115faa970..8f0246dee1d6 100644 --- a/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt +++ b/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt @@ -13,5 +13,11 @@ try { } ?> DONE ---EXPECT-- -DONE +--EXPECTF-- +Array + +Fatal error: Uncaught Exception in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(2, 'Array to string...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/temporary_cleaning/temporary_cleaning_016.phpt b/Zend/tests/temporary_cleaning/temporary_cleaning_016.phpt index 8dc4c8ea3148..1a920b50d22d 100644 --- a/Zend/tests/temporary_cleaning/temporary_cleaning_016.phpt +++ b/Zend/tests/temporary_cleaning/temporary_cleaning_016.phpt @@ -13,4 +13,9 @@ try { DONE --EXPECTF-- Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d -DONE + +Fatal error: Uncaught Exception in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(2, 'Array to string...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/try/catch_novar_2.phpt b/Zend/tests/try/catch_novar_2.phpt index fa1ada927534..c36367b26682 100644 --- a/Zend/tests/try/catch_novar_2.phpt +++ b/Zend/tests/try/catch_novar_2.phpt @@ -11,16 +11,18 @@ class ThrowsOnDestruct extends Exception { try { throw new ThrowsOnDestruct(); } catch (Exception) { - echo "Unreachable catch\n"; + echo "Caught\n"; } -echo "Unreachable fallthrough\n"; +echo "After try/catch\n"; ?> --EXPECTF-- +Caught +After try/catch Throwing Fatal error: Uncaught RuntimeException: ThrowsOnDestruct::__destruct in %s:%d Stack trace: -#0 %s(%d): ThrowsOnDestruct->__destruct() +#0 [internal function]: ThrowsOnDestruct->__destruct() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra1.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra1.phpt index 42b91f4a656d..47bd2c6b05bc 100644 --- a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra1.phpt +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra1.phpt @@ -14,5 +14,5 @@ var_dump($b | 1); ?> --EXPECTF-- -Implicit conversion from float-string "1.0E+4%d" to int loses precision int(%d) +Implicit conversion from float-string "1.0E+4%d" to int loses precision diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt index 0bfbeb01a2d0..5d44d8021910 100644 --- a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt @@ -14,5 +14,5 @@ var_dump(isset($ary[1.0E+42])); ?> --EXPECT-- +bool(true) The float 1.0E+42 is not representable as an int, cast occurred -bool(false) diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt index 8134ce08d2ee..3f49fcea85ba 100644 --- a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt @@ -14,5 +14,5 @@ var_dump(\array_key_exists(1.0E+42, $ary)); ?> --EXPECT-- +bool(true) The float 1.0E+42 is not representable as an int, cast occurred -bool(false) diff --git a/Zend/tests/type_coercion/gh22112.phpt b/Zend/tests/type_coercion/gh22112.phpt index 84fdc393a828..dbbaf66757b9 100644 --- a/Zend/tests/type_coercion/gh22112.phpt +++ b/Zend/tests/type_coercion/gh22112.phpt @@ -31,5 +31,7 @@ try { ?> --EXPECT-- +take_bool entered bool: unexpected NAN value was coerced to bool +take_string entered string: unexpected NAN value was coerced to string diff --git a/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt b/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt index 027e4b77e5dd..07774bb72f47 100644 --- a/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt +++ b/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt @@ -26,5 +26,5 @@ do_it(); ?> --EXPECT-- Before -WithDestructor::__destruct After +WithDestructor::__destruct diff --git a/Zend/tests/undef_index_to_exception.phpt b/Zend/tests/undef_index_to_exception.phpt index bbe13c0e71d0..5ed70b1f1494 100644 --- a/Zend/tests/undef_index_to_exception.phpt +++ b/Zend/tests/undef_index_to_exception.phpt @@ -35,12 +35,9 @@ try { } ?> ---EXPECT-- -Undefined array key 0 -array(0) { -} -Undefined array key "key" -array(0) { -} -Undefined global variable $test -Undefined variable $test +--EXPECTF-- +Fatal error: Uncaught Exception: Undefined array key 0 in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(2, 'Undefined array...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/undef_var_in_verify_return.phpt b/Zend/tests/undef_var_in_verify_return.phpt index f3966c6992d6..0a9dff20343f 100644 --- a/Zend/tests/undef_var_in_verify_return.phpt +++ b/Zend/tests/undef_var_in_verify_return.phpt @@ -15,9 +15,14 @@ test(); ?> --EXPECTF-- -Fatal error: Uncaught ErrorException: Undefined variable $test in %s:%d +Fatal error: Uncaught TypeError: test(): Return value must be of type string, null returned in %s:%d +Stack trace: +#0 %s(%d): test() +#1 {main} + +Next ErrorException: Undefined variable $test in %s:%d Stack trace: #0 %s(%d): {closure:%s:%d}(2, 'Undefined varia...', '%s', 8) #1 %s(%d): test() #2 {main} - thrown in %s on line %d + thrown in %s on line %d \ No newline at end of file diff --git a/Zend/tests/unset/unset_prop_recursion.phpt b/Zend/tests/unset/unset_prop_recursion.phpt index afb1929424f8..3c3a36ed8cb6 100644 --- a/Zend/tests/unset/unset_prop_recursion.phpt +++ b/Zend/tests/unset/unset_prop_recursion.phpt @@ -43,9 +43,9 @@ object(Node)#1 (2) { } } } -object(Node)#2 (2) { +object(Node)#3 (2) { ["parent"]=> - object(Node)#1 (2) { + object(Node)#1 (1) { ["parent"]=> NULL } @@ -53,9 +53,9 @@ object(Node)#2 (2) { array(0) { } } -object(Node)#3 (2) { +object(Node)#2 (2) { ["parent"]=> - object(Node)#1 (2) { + object(Node)#1 (1) { ["parent"]=> NULL } diff --git a/Zend/tests/weakrefs/gh13612.phpt b/Zend/tests/weakrefs/gh13612.phpt index 4ca4c9250876..327155a34246 100644 --- a/Zend/tests/weakrefs/gh13612.phpt +++ b/Zend/tests/weakrefs/gh13612.phpt @@ -35,5 +35,5 @@ echo "Done\n"; ?> --EXPECT-- -NULL Done +NULL diff --git a/Zend/tests/weakrefs/weakmap_iteration.phpt b/Zend/tests/weakrefs/weakmap_iteration.phpt index 1d1f6def8f48..60f34d78663a 100644 --- a/Zend/tests/weakrefs/weakmap_iteration.phpt +++ b/Zend/tests/weakrefs/weakmap_iteration.phpt @@ -38,24 +38,24 @@ var_dump($map); Empty loop: Simple loop: -object(stdClass)#2 (0) { +object(stdClass)#3 (0) { } int(0) -object(stdClass)#3 (0) { +object(stdClass)#4 (0) { } int(1) -object(stdClass)#4 (0) { +object(stdClass)#5 (0) { } int(2) Object removed during loop: -object(stdClass)#2 (0) { +object(stdClass)#3 (0) { } int(0) -object(stdClass)#3 (0) { +object(stdClass)#4 (0) { } int(1) -object(stdClass)#4 (0) { +object(stdClass)#5 (0) { } int(2) @@ -64,7 +64,7 @@ object(WeakMap)#1 (2) { [0]=> array(2) { ["key"]=> - object(stdClass)#2 (0) { + object(stdClass)#3 (0) { } ["value"]=> &int(1) @@ -72,7 +72,7 @@ object(WeakMap)#1 (2) { [1]=> array(2) { ["key"]=> - object(stdClass)#4 (0) { + object(stdClass)#5 (0) { } ["value"]=> &int(3) diff --git a/Zend/tests/weakrefs/weakmap_weakness.phpt b/Zend/tests/weakrefs/weakmap_weakness.phpt index d740d2b219c1..84d9fde53515 100644 --- a/Zend/tests/weakrefs/weakmap_weakness.phpt +++ b/Zend/tests/weakrefs/weakmap_weakness.phpt @@ -78,13 +78,13 @@ object(WeakMap)#1 (0) { Destructor in WeakMap value: Before unset: -Dtor! After unset: +Dtor! object(WeakMap)#1 (0) { } Destroying map with live object: -object(stdClass)#2 (0) { +object(stdClass)#3 (0) { } Object freed by GC: @@ -92,7 +92,7 @@ object(WeakMap)#1 (1) { [0]=> array(2) { ["key"]=> - object(stdClass)#3 (1) { + object(stdClass)#2 (1) { ["obj"]=> *RECURSION* } @@ -104,7 +104,7 @@ object(WeakMap)#1 (0) { } Storing object as own value: -object(WeakMap)#3 (1) { +object(WeakMap)#2 (1) { [0]=> array(2) { ["key"]=> @@ -117,7 +117,7 @@ object(WeakMap)#3 (1) { } Storing map in itself: -object(WeakMap)#3 (1) { +object(WeakMap)#2 (1) { [0]=> array(2) { ["key"]=> diff --git a/Zend/zend.c b/Zend/zend.c index 07692db85196..8ab8466e7bd2 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1438,9 +1438,10 @@ ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */ } \ } while (0) -ZEND_API ZEND_COLD void zend_error_zstr_at( +static void zend_call_user_error_handler( int orig_type, zend_string *error_filename, uint32_t error_lineno, zend_string *message) { + int type = orig_type & E_ALL; zval params[4]; zval retval; zval orig_user_error_handler; @@ -1448,11 +1449,204 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( zend_class_entry *saved_class_entry = NULL; zend_stack loop_var_stack; zend_stack delayed_oplines_stack; - int type = orig_type & E_ALL; bool orig_record_errors; zend_err_buf orig_errors_buf; zend_result res; + if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF + || !(EG(user_error_handler_error_reporting) & type) + || EG(error_handling) != EH_NORMAL) { + zend_error_cb(orig_type, error_filename, error_lineno, message); + return; + } + + zend_flush_deferred_dtors(); + zend_flush_deferred_errors(); + + if (UNEXPECTED(EG(exception))) { + return; + } + + ZVAL_STR_COPY(¶ms[1], message); + ZVAL_LONG(¶ms[0], type); + + if (error_filename) { + ZVAL_STR_COPY(¶ms[2], error_filename); + } else { + ZVAL_NULL(¶ms[2]); + } + + ZVAL_LONG(¶ms[3], error_lineno); + + ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); + ZVAL_UNDEF(&EG(user_error_handler)); + + /* User error handler may include() additional PHP files. + * If an error was generated during compilation PHP will compile + * such scripts recursively, but some CG() variables may be + * inconsistent. */ + + in_compilation = CG(in_compilation); + if (in_compilation) { + saved_class_entry = CG(active_class_entry); + CG(active_class_entry) = NULL; + SAVE_STACK(loop_var_stack); + SAVE_STACK(delayed_oplines_stack); + CG(in_compilation) = 0; + } + + orig_record_errors = EG(record_errors); + EG(record_errors) = false; + + orig_errors_buf = EG(errors); + memset(&EG(errors), 0, sizeof(EG(errors))); + + res = call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params); + + EG(record_errors) = orig_record_errors; + EG(errors) = orig_errors_buf; + + if (res == SUCCESS) { + if (Z_TYPE(retval) != IS_UNDEF) { + if (Z_TYPE(retval) == IS_FALSE) { + zend_error_cb(orig_type, error_filename, error_lineno, message); + } + zval_ptr_dtor(&retval); + } + } else if (!EG(exception)) { + /* The user error handler failed, use built-in error handler */ + zend_error_cb(orig_type, error_filename, error_lineno, message); + } + + if (in_compilation) { + CG(active_class_entry) = saved_class_entry; + RESTORE_STACK(loop_var_stack); + RESTORE_STACK(delayed_oplines_stack); + CG(in_compilation) = 1; + } + + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[1]); + + if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF) { + ZVAL_COPY_VALUE(&EG(user_error_handler), &orig_user_error_handler); + } else { + zval_ptr_dtor(&orig_user_error_handler); + } +} + +static zend_always_inline bool zend_can_defer_error(int type) +{ + if (type == E_USER_ERROR || type == E_RECOVERABLE_ERROR) { + return false; + } + if (CG(in_compilation) || !EG(current_execute_data) || !EG(current_execute_data)->func) { + return false; + } + zend_execute_data *ex = EG(current_execute_data); + if (!ZEND_USER_CODE(ex->func->type) || !ex->opline) { + return false; + } + switch (ex->opline->opcode) { + case ZEND_DECLARE_CLASS: + case ZEND_DECLARE_CLASS_DELAYED: + case ZEND_DECLARE_ANON_CLASS: + case ZEND_INIT_FCALL: + case ZEND_INIT_FCALL_BY_NAME: + case ZEND_INIT_NS_FCALL_BY_NAME: + case ZEND_INIT_METHOD_CALL: + case ZEND_INIT_STATIC_METHOD_CALL: + case ZEND_INIT_USER_CALL: + case ZEND_INIT_DYNAMIC_CALL: + case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL: + case ZEND_DO_FCALL: + case ZEND_DO_FCALL_BY_NAME: + case ZEND_DO_UCALL: + case ZEND_FETCH_CONSTANT: + case ZEND_FETCH_CLASS_CONSTANT: + case ZEND_INCLUDE_OR_EVAL: + return false; + } + return true; +} + +static void zend_defer_error( + int orig_type, zend_string *error_filename, uint32_t error_lineno, zend_string *message) +{ + zend_error_info *info = emalloc(sizeof(zend_error_info)); + info->type = orig_type; + info->lineno = error_lineno; + info->error_reporting = EG(error_reporting); + info->filename = error_filename ? zend_string_copy(error_filename) : NULL; + info->message = zend_string_copy(message); + + EG(deferred_errors).size++; + if (EG(deferred_errors).size > EG(deferred_errors).capacity) { + uint32_t capacity = EG(deferred_errors).capacity + ? EG(deferred_errors).capacity + (EG(deferred_errors).capacity >> 1) : 2; + EG(deferred_errors).errors = erealloc(EG(deferred_errors).errors, sizeof(zend_error_info *) * capacity); + EG(deferred_errors).capacity = capacity; + } + EG(deferred_errors).errors[EG(deferred_errors).size - 1] = info; + + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); +} + +ZEND_API void zend_flush_deferred_errors(void) +{ + if (!EG(deferred_errors).size) { + return; + } + + /* A user error handler cannot run while an exception is pending. Keep the + * errors buffered so ZEND_HANDLE_EXCEPTION can flush them with the + * exception cleared, instead of silently dropping them. */ + if (EG(exception)) { + return; + } + + zend_err_buf buf = EG(deferred_errors); + memset(&EG(deferred_errors), 0, sizeof(EG(deferred_errors))); + + int orig_error_reporting = EG(error_reporting); + for (uint32_t i = 0; i < buf.size; i++) { + zend_error_info *info = buf.errors[i]; + if (!EG(exception)) { + EG(error_reporting) = info->error_reporting; + zend_call_user_error_handler(info->type, info->filename, info->lineno, info->message); + } + if (info->filename) { + zend_string_release(info->filename); + } + zend_string_release(info->message); + efree_size(info, sizeof(zend_error_info)); + } + EG(error_reporting) = orig_error_reporting; + efree(buf.errors); +} + +ZEND_API void zend_free_deferred_errors(void) +{ + if (!EG(deferred_errors).size) { + return; + } + for (uint32_t i = 0; i < EG(deferred_errors).size; i++) { + zend_error_info *info = EG(deferred_errors).errors[i]; + if (info->filename) { + zend_string_release(info->filename); + } + zend_string_release(info->message); + efree_size(info, sizeof(zend_error_info)); + } + efree(EG(deferred_errors).errors); + memset(&EG(deferred_errors), 0, sizeof(EG(deferred_errors))); +} + +ZEND_API ZEND_COLD void zend_error_zstr_at( + int orig_type, zend_string *error_filename, uint32_t error_lineno, zend_string *message) +{ + int type = orig_type & E_ALL; + /* If we're executing a function during SCCP, count any warnings that may be emitted, * but don't perform any other error handling. */ if (EG(capture_warnings_during_sccp)) { @@ -1485,6 +1679,7 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( zend_error_info *info = emalloc(sizeof(zend_error_info)); info->type = type; info->lineno = error_lineno; + info->error_reporting = EG(error_reporting); info->filename = zend_string_copy(error_filename); info->message = zend_string_copy(message); EG(errors).size++; @@ -1546,72 +1741,10 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( zend_error_cb(orig_type, error_filename, error_lineno, message); break; default: - /* Handle the error in user space */ - ZVAL_STR_COPY(¶ms[1], message); - ZVAL_LONG(¶ms[0], type); - - if (error_filename) { - ZVAL_STR_COPY(¶ms[2], error_filename); - } else { - ZVAL_NULL(¶ms[2]); - } - - ZVAL_LONG(¶ms[3], error_lineno); - - ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); - ZVAL_UNDEF(&EG(user_error_handler)); - - /* User error handler may include() additional PHP files. - * If an error was generated during compilation PHP will compile - * such scripts recursively, but some CG() variables may be - * inconsistent. */ - - in_compilation = CG(in_compilation); - if (in_compilation) { - saved_class_entry = CG(active_class_entry); - CG(active_class_entry) = NULL; - SAVE_STACK(loop_var_stack); - SAVE_STACK(delayed_oplines_stack); - CG(in_compilation) = 0; - } - - orig_record_errors = EG(record_errors); - EG(record_errors) = false; - - orig_errors_buf = EG(errors); - memset(&EG(errors), 0, sizeof(EG(errors))); - - res = call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params); - - EG(record_errors) = orig_record_errors; - EG(errors) = orig_errors_buf; - - if (res == SUCCESS) { - if (Z_TYPE(retval) != IS_UNDEF) { - if (Z_TYPE(retval) == IS_FALSE) { - zend_error_cb(orig_type, error_filename, error_lineno, message); - } - zval_ptr_dtor(&retval); - } - } else if (!EG(exception)) { - /* The user error handler failed, use built-in error handler */ - zend_error_cb(orig_type, error_filename, error_lineno, message); - } - - if (in_compilation) { - CG(active_class_entry) = saved_class_entry; - RESTORE_STACK(loop_var_stack); - RESTORE_STACK(delayed_oplines_stack); - CG(in_compilation) = 1; - } - - zval_ptr_dtor(¶ms[2]); - zval_ptr_dtor(¶ms[1]); - - if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF) { - ZVAL_COPY_VALUE(&EG(user_error_handler), &orig_user_error_handler); + if (zend_can_defer_error(type)) { + zend_defer_error(orig_type, error_filename, error_lineno, message); } else { - zval_ptr_dtor(&orig_user_error_handler); + zend_call_user_error_handler(orig_type, error_filename, error_lineno, message); } break; } @@ -1974,7 +2107,12 @@ ZEND_API zend_result zend_execute_script(int type, zval *retval, zend_file_handl zend_result ret = SUCCESS; if (op_array) { + zend_execute_data *previous_execute_data = EG(current_execute_data); zend_execute(op_array, retval); + EG(current_execute_data) = previous_execute_data; + zend_flush_deferred_dtors(); + zend_surface_deferred_dtor_exception(); + zend_flush_deferred_errors(); if (UNEXPECTED(EG(exception))) { if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { zend_user_exception_handler(); diff --git a/Zend/zend.h b/Zend/zend.h index 0d5303192b57..302f76039295 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -128,6 +128,7 @@ typedef struct _zend_inheritance_cache_entry zend_inheritance_cache_entry; typedef struct _zend_error_info { int type; uint32_t lineno; + int error_reporting; zend_string *filename; zend_string *message; } zend_error_info; @@ -453,6 +454,8 @@ ZEND_API void zend_begin_record_errors(void); ZEND_API void zend_emit_recorded_errors(void); ZEND_API void zend_emit_recorded_errors_ex(uint32_t num_errors, zend_error_info **errors); ZEND_API void zend_free_recorded_errors(void); +ZEND_API void zend_flush_deferred_errors(void); +ZEND_API void zend_free_deferred_errors(void); END_EXTERN_C() #define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ac5a9d71a6ea..0066fe744463 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6009,6 +6009,10 @@ static void zend_compile_return(const zend_ast *ast) /* {{{ */ expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, false); } + if (CG(context).try_catch_offset != (uint32_t)-1) { + zend_emit_op(NULL, ZEND_FLUSH_DEFERRED_DTORS, NULL, NULL); + } + uint32_t opnum_before_finally = get_next_op_number(); zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL); @@ -6076,6 +6080,8 @@ static void zend_compile_throw(znode *result, const zend_ast *ast) /* {{{ */ znode expr_node; zend_compile_expr(&expr_node, expr_ast); + zend_emit_op(NULL, ZEND_FLUSH_DEFERRED_DTORS, NULL, NULL); + zend_op *opline = zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL); if (result) { /* Mark this as an "expression throw" for opcache. */ @@ -6117,6 +6123,9 @@ static void zend_compile_break_continue(const zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "'%s' not in the 'loop' or 'switch' context", ast->kind == ZEND_AST_BREAK ? "break" : "continue"); } else { + if (CG(context).try_catch_offset != (uint32_t)-1) { + zend_emit_op(NULL, ZEND_FLUSH_DEFERRED_DTORS, NULL, NULL); + } if (!zend_handle_loops_and_finally_ex(depth, NULL)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' " ZEND_LONG_FMT " level%s", ast->kind == ZEND_AST_BREAK ? "break" : "continue", @@ -6232,6 +6241,10 @@ static void zend_compile_goto(const zend_ast *ast) /* {{{ */ zend_compile_expr(&label_node, label_ast); + if (CG(context).try_catch_offset != (uint32_t)-1) { + zend_emit_op(NULL, ZEND_FLUSH_DEFERRED_DTORS, NULL, NULL); + } + /* Label resolution and unwinding adjustments happen in pass two. */ uint32_t opnum_start = get_next_op_number(); zend_handle_loops_and_finally(NULL); @@ -7041,6 +7054,8 @@ static void zend_compile_try(const zend_ast *ast) /* {{{ */ } ZEND_HASH_FOREACH_END(); } + zend_emit_op(NULL, ZEND_FLUSH_DEFERRED_DTORS, NULL, NULL); + try_catch_offset = zend_add_try_element(get_next_op_number()); if (finally_ast) { @@ -7062,6 +7077,8 @@ static void zend_compile_try(const zend_ast *ast) /* {{{ */ zend_compile_stmt(try_ast); + zend_emit_op(NULL, ZEND_FLUSH_DEFERRED_DTORS, NULL, NULL); + if (catches->children != 0) { jmp_opnums[0] = zend_emit_jump(0); } @@ -7164,6 +7181,8 @@ static void zend_compile_try(const zend_ast *ast) /* {{{ */ zend_compile_stmt(finally_ast); + zend_emit_op(NULL, ZEND_FLUSH_DEFERRED_DTORS, NULL, NULL); + CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1; CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = get_next_op_number(); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 1b28ce25fe37..6cf5fdca2863 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4316,13 +4316,73 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *ca zend_atomic_bool_store_ex(&EG(vm_interrupt), false); if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); - } else if (zend_interrupt_function) { - zend_interrupt_function(call); + } else { + zend_flush_deferred_errors(); + if (zend_interrupt_function) { + zend_interrupt_function(call); + } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } + } +} + +static zend_always_inline bool zend_interrupt_process( + zend_execute_data *execute_data, const zend_op *opline, bool flush_dtors) +{ + bool entered = false; + bool pending_dtors = EG(deferred_dtors).count || EG(deferred_dtors).values_count; + + if (EG(deferred_errors).size || pending_dtors) { + if (EX(call) + || opline->opcode == ZEND_DO_FCALL + || opline->opcode == ZEND_DO_ICALL + || opline->opcode == ZEND_DO_UCALL + || opline->opcode == ZEND_DO_FCALL_BY_NAME) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } else { + if (flush_dtors + || (pending_dtors + && opline >= EX(func)->op_array.opcodes + && opline <= EX(func)->op_array.opcodes + EX(func)->op_array.num_args)) { + zend_flush_deferred_dtors(); + entered = true; + } else if (pending_dtors) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } + if (EG(deferred_errors).size) { + zend_flush_deferred_errors(); + entered = true; + } + } + } + if (zend_interrupt_function) { + zend_interrupt_function(execute_data); + entered = true; + } + + return entered; +} + +static zend_always_inline void zend_interrupt_handle_exception(void) +{ + if (EG(exception)) { + const zend_op *throw_op = EG(opline_before_exception); + + if (throw_op + && throw_op->result_type & (IS_TMP_VAR|IS_VAR) + && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT + && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK + && throw_op->opcode != ZEND_ROPE_INIT + && throw_op->opcode != ZEND_ROPE_ADD) { + ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); + } } } #define ZEND_VM_INTERRUPT_CHECK() do { \ if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \ + SAVE_OPLINE(); \ ZEND_VM_INTERRUPT(); \ } \ } while (0) @@ -4781,6 +4841,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o { if (UNEXPECTED(EX(call))) { zend_execute_data *call = EX(call); + EG(frame_teardown)++; zend_op *opline = EX(func)->op_array.opcodes + op_num; int level; int do_exit; @@ -4909,12 +4970,14 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o zend_vm_stack_free_call_frame(call); call = EX(call); } while (call); + EG(frame_teardown)--; } } /* }}} */ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */ { + EG(frame_teardown)++; for (uint32_t i = 0; i < EX(func)->op_array.last_live_range; i++) { const zend_live_range *range = &EX(func)->op_array.live_range[i]; if (range->start > op_num) { @@ -4975,6 +5038,7 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, } } } + EG(frame_teardown)--; } /* }}} */ @@ -5784,9 +5848,22 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint CHECK_SYMBOL_TABLES() \ OPLINE = new_op -#define ZEND_VM_SET_OPCODE(new_op) \ - ZEND_VM_SET_OPCODE_NO_INTERRUPT(new_op); \ - ZEND_VM_INTERRUPT_CHECK() +#define ZEND_VM_SET_OPCODE(new_op) do { \ + const zend_op *_target = (new_op); \ + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \ + bool _backward = _target <= OPLINE; \ + ZEND_VM_SET_OPCODE_NO_INTERRUPT(_target); \ + if (_backward) { \ + ZEND_VM_KIND_TAILCALL_SAVE_OPLINE(); \ + ZEND_VM_LOOP_INTERRUPT(); \ + } else { \ + SAVE_OPLINE(); \ + ZEND_VM_INTERRUPT(); \ + } \ + } else { \ + ZEND_VM_SET_OPCODE_NO_INTERRUPT(_target); \ + } \ + } while (0) #define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \ ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset)) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index cb48e6234371..37ecdd7d8e01 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -192,6 +192,11 @@ void init_executor(void) /* {{{ */ EG(record_errors) = false; memset(&EG(errors), 0, sizeof(EG(errors))); + memset(&EG(deferred_errors), 0, sizeof(EG(deferred_errors))); + memset(&EG(deferred_dtors), 0, sizeof(EG(deferred_dtors))); + EG(deferred_dtor_exception) = NULL; + EG(dtor_defer_gate) = 1; + EG(frame_teardown) = 0; EG(filename_override) = NULL; EG(lineno_override) = -1; @@ -257,11 +262,21 @@ void shutdown_destructors(void) /* {{{ */ do { symbols = zend_hash_num_elements(&EG(symbol_table)); zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor); - } while (symbols != zend_hash_num_elements(&EG(symbol_table))); + zend_flush_deferred_dtors(); + zend_surface_deferred_dtor_exception(); + } while (symbols != zend_hash_num_elements(&EG(symbol_table)) + || (!EG(exception) && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))); zend_objects_store_call_destructors(&EG(objects_store)); + zend_flush_deferred_dtors(); + zend_surface_deferred_dtor_exception(); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_exception_error(EG(exception), E_ERROR); + zend_bailout(); + } } zend_catch { /* if we couldn't destruct cleanly, mark all objects as destructed anyway */ zend_objects_store_mark_destructed(&EG(objects_store)); + zend_release_deferred_dtors(); } zend_end_try(); } /* }}} */ @@ -445,6 +460,13 @@ void shutdown_executor(void) /* {{{ */ bool fast_shutdown = is_zend_mm() && !EG(full_tables_cleanup); #endif + zend_free_deferred_errors(); + if (EG(deferred_dtor_exception)) { + GC_DELREF(EG(deferred_dtor_exception)); + EG(deferred_dtor_exception) = NULL; + } + zend_release_deferred_dtors(); + zend_try { zend_stream_shutdown(); } zend_end_try(); @@ -869,6 +891,14 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ } #endif + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !EG(frame_teardown))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + return SUCCESS; + } + } + call = zend_vm_stack_push_call_frame(call_info, func, fci->param_count, object_or_called_scope); uint32_t consumed_args = fci->param_count ? fci->consumed_args : 0; @@ -1055,6 +1085,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ #endif ZEND_OBSERVER_FCALL_END(call, fci->retval); EG(current_execute_data) = call->prev_execute_data; + EG(frame_teardown)++; zend_vm_stack_free_args(call); if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { zend_array_release(call->extra_named_params); @@ -1064,6 +1095,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ zval_ptr_dtor(fci->retval); ZVAL_UNDEF(fci->retval); } + EG(frame_teardown)--; /* This flag is regularly checked while running user functions, but not internal * So see whether interrupt flag was set while the function was running... */ @@ -1074,9 +1106,14 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ zend_interrupt_function(EG(current_execute_data)); } } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { + EG(frame_teardown)++; OBJ_RELEASE(Z_OBJ(call->This)); + EG(frame_teardown)--; } } EG(fake_scope) = orig_fake_scope; @@ -1085,7 +1122,9 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ if (UNEXPECTED(EG(exception))) { if (UNEXPECTED(!EG(current_execute_data))) { - zend_throw_exception_internal(NULL); + if (!EG(frame_teardown)) { + zend_throw_exception_internal(NULL); + } } else if (EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { zend_rethrow_exception(EG(current_execute_data)); diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index c91436050856..37315a8d014b 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -113,6 +113,9 @@ typedef struct _zend_fiber_vm_state { uint32_t jit_trace_num; JMP_BUF *bailout; zend_fiber *active_fiber; + zend_dtor_buf deferred_dtors; + uint32_t dtor_defer_gate; + uint32_t frame_teardown; #ifdef ZEND_CHECK_STACK_LIMIT void *stack_base; void *stack_limit; @@ -130,6 +133,9 @@ static zend_always_inline void zend_fiber_capture_vm_state(zend_fiber_vm_state * state->jit_trace_num = EG(jit_trace_num); state->bailout = EG(bailout); state->active_fiber = EG(active_fiber); + state->deferred_dtors = EG(deferred_dtors); + state->dtor_defer_gate = EG(dtor_defer_gate); + state->frame_teardown = EG(frame_teardown); #ifdef ZEND_CHECK_STACK_LIMIT state->stack_base = EG(stack_base); state->stack_limit = EG(stack_limit); @@ -147,10 +153,17 @@ static zend_always_inline void zend_fiber_restore_vm_state(zend_fiber_vm_state * EG(jit_trace_num) = state->jit_trace_num; EG(bailout) = state->bailout; EG(active_fiber) = state->active_fiber; + EG(deferred_dtors) = state->deferred_dtors; + EG(dtor_defer_gate) = state->dtor_defer_gate; + EG(frame_teardown) = state->frame_teardown; #ifdef ZEND_CHECK_STACK_LIMIT EG(stack_base) = state->stack_base; EG(stack_limit) = state->stack_limit; #endif + + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } } #ifdef ZEND_FIBER_UCONTEXT @@ -598,6 +611,10 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer) EG(jit_trace_num) = 0; EG(error_reporting) = error_reporting; + memset(&EG(deferred_dtors), 0, sizeof(EG(deferred_dtors))); + EG(dtor_defer_gate) = 1; + EG(frame_teardown) = 0; + #ifdef ZEND_CHECK_STACK_LIMIT EG(stack_base) = zend_fiber_stack_base(fiber->context.stack); EG(stack_limit) = zend_fiber_stack_limit(fiber->context.stack); @@ -607,6 +624,10 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer) zend_call_function(&fiber->fci, &fiber->fci_cache); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + } + /* Cleanup callback and unset field to prevent GC / duplicate dtor issues. */ zval_ptr_dtor(&fiber->fci.function_name); ZVAL_UNDEF(&fiber->fci.function_name); @@ -626,6 +647,7 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer) } zend_catch { fiber->flags |= ZEND_FIBER_FLAG_BAILOUT; transfer->flags = ZEND_FIBER_TRANSFER_FLAG_BAILOUT; + zend_release_deferred_dtors(); } zend_end_try(); fiber->context.cleanup = &zend_fiber_cleanup; diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 5de2b69bf568..cf37cdd9bf83 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -732,6 +732,23 @@ static zend_never_inline void ZEND_FASTCALL gc_possible_root_when_full(zend_refc GC_BENCH_PEAK(root_buf_peak, root_buf_length); } +ZEND_API bool ZEND_FASTCALL zend_gc_is_condemned(zend_refcounted *ref) +{ + uint32_t idx = GC_REF_ADDRESS(ref); + + if (idx == 0) { + return false; + } + + gc_root_buffer *slot; + if (UNEXPECTED(GC_G(first_unused) >= GC_MAX_UNCOMPRESSED)) { + slot = gc_decompress(ref, idx); + } else { + slot = GC_IDX2PTR(idx); + } + return GC_IS_GARBAGE(slot->ref) || GC_IS_DTOR_GARBAGE(slot->ref); +} + /* Add a possible root node to the buffer. * Maybe perform a GC run. */ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref) @@ -743,6 +760,11 @@ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref) return; } + if (UNEXPECTED(GC_TYPE(ref) == IS_OBJECT + && (OBJ_EXTRA_FLAGS((zend_object*)ref) & IS_OBJ_DTOR_PENDING))) { + return; + } + GC_BENCH_INC(zval_possible_root); if (EXPECTED(GC_HAS_UNUSED())) { diff --git a/Zend/zend_gc.h b/Zend/zend_gc.h index b72b90ccd5ef..7a872d1fe19f 100644 --- a/Zend/zend_gc.h +++ b/Zend/zend_gc.h @@ -46,6 +46,7 @@ ZEND_API extern int (*gc_collect_cycles)(void); ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref); ZEND_API void ZEND_FASTCALL gc_remove_from_buffer(zend_refcounted *ref); +ZEND_API bool ZEND_FASTCALL zend_gc_is_condemned(zend_refcounted *ref); /* enable/disable automatic start of GC collection */ ZEND_API bool gc_enable(bool enable); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 52d409f2e69b..bbbfb544646e 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -130,14 +130,70 @@ static void zend_generator_cleanup_unfinished_execution( } /* }}} */ +static void zend_generator_drain_deferred_dtors(zend_generator *generator) +{ + if (EXPECTED(!generator->deferred_dtors.count && !generator->deferred_dtors.values_count)) { + return; + } + + zend_dtor_buf original_deferred_dtors = EG(deferred_dtors); + + EG(deferred_dtors) = generator->deferred_dtors; + memset(&generator->deferred_dtors, 0, sizeof(generator->deferred_dtors)); + + if (UNEXPECTED(CG(unclean_shutdown))) { + zend_release_deferred_dtors(); + } else { + zend_flush_deferred_dtors(); + } + + EG(deferred_dtors) = original_deferred_dtors; +} + +static zend_always_inline void zend_generator_enter_dtor_state(zend_generator *generator, zend_dtor_buf *deferred_dtors, uint32_t *dtor_defer_gate, uint32_t *frame_teardown) +{ + *deferred_dtors = EG(deferred_dtors); + *dtor_defer_gate = EG(dtor_defer_gate); + *frame_teardown = EG(frame_teardown); + + EG(deferred_dtors) = generator->deferred_dtors; + EG(dtor_defer_gate) = generator->dtor_defer_gate; + EG(frame_teardown) = generator->frame_teardown; + + memset(&generator->deferred_dtors, 0, sizeof(generator->deferred_dtors)); + generator->frame_teardown = 0; + + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } +} + +static zend_always_inline void zend_generator_leave_dtor_state(zend_generator *generator, const zend_dtor_buf *deferred_dtors, uint32_t dtor_defer_gate, uint32_t frame_teardown) +{ + generator->deferred_dtors = EG(deferred_dtors); + generator->dtor_defer_gate = EG(dtor_defer_gate); + generator->frame_teardown = EG(frame_teardown); + + EG(deferred_dtors) = *deferred_dtors; + EG(dtor_defer_gate) = dtor_defer_gate; + EG(frame_teardown) = frame_teardown; + + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } +} + ZEND_API void zend_generator_close(zend_generator *generator, bool finished_execution) /* {{{ */ { + zend_generator_drain_deferred_dtors(generator); + if (EXPECTED(generator->execute_data)) { zend_execute_data *execute_data = generator->execute_data; /* Null out execute_data early, to prevent double frees if GC runs while we're * already cleaning up execute_data. */ generator->execute_data = NULL; + EG(frame_teardown)++; if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { zend_clean_and_cache_symbol_table(execute_data->symbol_table); } @@ -150,6 +206,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, bool finished_exec if (EX_CALL_INFO() & ZEND_CALL_RELEASE_THIS) { OBJ_RELEASE(Z_OBJ(execute_data->This)); } + EG(frame_teardown)--; /* A fatal error / die occurred during the generator execution. * Trying to clean up the stack may not be safe in this case. */ @@ -158,7 +215,9 @@ ZEND_API void zend_generator_close(zend_generator *generator, bool finished_exec return; } + EG(frame_teardown)++; zend_vm_stack_free_extra_args(execute_data); + EG(frame_teardown)--; /* Some cleanups are only necessary if the generator was closed * before it could finish execution (reach a return statement). */ @@ -470,6 +529,8 @@ static zend_object *zend_generator_create(zend_class_entry *class_type) /* {{{ * /* The key will be incremented on first use, so it'll start at 0 */ generator->largest_used_integer_key = -1; + generator->dtor_defer_gate = 1; + ZVAL_UNDEF(&generator->retval); ZVAL_UNDEF(&generator->values); @@ -519,12 +580,17 @@ static zend_result zend_generator_throw_exception(zend_generator *generator, zva } zend_execute_data *original_execute_data = EG(current_execute_data); + zend_dtor_buf original_deferred_dtors; + uint32_t original_dtor_defer_gate; + uint32_t original_frame_teardown; /* Throw the exception in the context of the generator. Decrementing the opline * to pretend the exception happened during the YIELD opcode. */ EG(current_execute_data) = generator->execute_data; generator->execute_data->prev_execute_data = original_execute_data; + zend_generator_enter_dtor_state(generator, &original_deferred_dtors, &original_dtor_defer_gate, &original_frame_teardown); + if (exception) { zend_throw_exception_object(exception); } else { @@ -537,6 +603,7 @@ static zend_result zend_generator_throw_exception(zend_generator *generator, zva ZVAL_UNDEF(&generator->values); } + zend_generator_leave_dtor_state(generator, &original_deferred_dtors, original_dtor_defer_gate, original_frame_teardown); EG(current_execute_data) = original_execute_data; return SUCCESS; @@ -791,11 +858,16 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ /* Backup executor globals */ zend_execute_data *original_execute_data = EG(current_execute_data); uint32_t original_jit_trace_num = EG(jit_trace_num); + zend_dtor_buf original_deferred_dtors; + uint32_t original_dtor_defer_gate; + uint32_t original_frame_teardown; /* Set executor globals */ EG(current_execute_data) = generator->execute_data; EG(jit_trace_num) = 0; + zend_generator_enter_dtor_state(generator, &original_deferred_dtors, &original_dtor_defer_gate, &original_frame_teardown); + /* We want the backtrace to look as if the generator function was * called from whatever method we are current running (e.g. next()). * So we have to link generator call frame with caller call frame. */ @@ -814,6 +886,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ if (UNEXPECTED(!Z_ISUNDEF(generator->values))) { if (EXPECTED(zend_generator_get_next_delegated_value(generator) == SUCCESS)) { /* Restore executor globals */ + zend_generator_leave_dtor_state(generator, &original_deferred_dtors, original_dtor_defer_gate, original_frame_teardown); EG(current_execute_data) = original_execute_data; EG(jit_trace_num) = original_jit_trace_num; @@ -864,6 +937,12 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ EG(current_execute_data) = original_execute_data; EG(jit_trace_num) = original_jit_trace_num; + if (UNEXPECTED(!generator->execute_data) + && UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + } + zend_generator_leave_dtor_state(generator, &original_deferred_dtors, original_dtor_defer_gate, original_frame_teardown); + /* If an exception was thrown in the generator we have to internally * rethrow it in the parent scope. * In case we did yield from, the Exception must be rethrown into diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 73dd9ddc1f91..18d9b89db76c 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -22,6 +22,7 @@ #include #include "zend_compile.h" +#include "zend_globals.h" BEGIN_EXTERN_C() @@ -91,6 +92,10 @@ struct _zend_generator { * the generator is alive. */ zend_function *func; + zend_dtor_buf deferred_dtors; + uint32_t dtor_defer_gate; + uint32_t frame_teardown; + /* ZEND_GENERATOR_* flags */ uint8_t flags; }; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index f78567cfaa74..189e399774df 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -87,6 +87,15 @@ typedef struct zend_err_buf { zend_error_info **errors; } zend_err_buf; +typedef struct zend_dtor_buf { + uint32_t count; + uint32_t capacity; + zend_object **objects; + uint32_t values_count; + uint32_t values_capacity; + zval *values; +} zend_dtor_buf; + struct _zend_compiler_globals { zend_stack loop_var_stack; @@ -306,6 +315,16 @@ struct _zend_executor_globals { bool record_errors; zend_err_buf errors; + /* Diagnostics whose user error handler is deferred to the next VM + * safepoint, so the handler cannot run mid-opcode and corrupt a + * structure the opcode still holds a pointer into. */ + zend_err_buf deferred_errors; + + zend_dtor_buf deferred_dtors; + zend_object *deferred_dtor_exception; + uint32_t dtor_defer_gate; + uint32_t frame_teardown; + /* Override filename or line number of thrown errors and exceptions */ zend_string *filename_override; zend_long lineno_override; diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 474157e73d39..f32f382e577a 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -115,6 +115,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) zend_function *destructor = object->ce->destructor; if (destructor) { + uint32_t defer_flags = OBJ_EXTRA_FLAGS(object) + & (IS_OBJ_DTOR_PENDING|IS_OBJ_DTOR_VIS_FAIL); + + OBJ_EXTRA_FLAGS(object) &= ~(IS_OBJ_DTOR_PENDING|IS_OBJ_DTOR_VIS_FAIL); + if (UNEXPECTED(zend_object_is_lazy(object))) { return; } @@ -123,23 +128,32 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) const zend_op *old_opline_before_exception = NULL; if (destructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { - if (EG(current_execute_data)) { - zend_class_entry *scope = zend_get_executed_scope(); - /* Ensure that if we're calling a protected or private function, we're allowed to do so. */ - ZEND_ASSERT(!(destructor->common.fn_flags & ZEND_ACC_PUBLIC)); - if (!zend_check_method_accessible(destructor, scope)) { - zend_throw_error(NULL, + zend_class_entry *scope = NULL; + bool accessible; + + ZEND_ASSERT(!(destructor->common.fn_flags & ZEND_ACC_PUBLIC)); + if (defer_flags & IS_OBJ_DTOR_PENDING) { + accessible = !(defer_flags & IS_OBJ_DTOR_VIS_FAIL); + if (!accessible) { + scope = zend_get_executed_scope(); + } + } else { + scope = zend_get_executed_scope(); + accessible = zend_check_method_accessible(destructor, scope); + } + if (!accessible) { + if (EG(current_execute_data) || !(EG(flags) & EG_FLAGS_IN_SHUTDOWN)) { + zend_throw_exception_ex(zend_ce_error, 0, "Call to %s %s::__destruct() from %s%s", zend_visibility_string(destructor->common.fn_flags), ZSTR_VAL(object->ce->name), scope ? "scope " : "global scope", scope ? ZSTR_VAL(scope->name) : "" ); - return; + } else { + zend_error(E_WARNING, + "Call to %s %s::__destruct() from global scope during shutdown ignored", + zend_visibility_string(destructor->common.fn_flags), ZSTR_VAL(object->ce->name)); } - } else { - zend_error(E_WARNING, - "Call to %s %s::__destruct() from global scope during shutdown ignored", - zend_visibility_string(destructor->common.fn_flags), ZSTR_VAL(object->ce->name)); return; } } diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 537cad8a3644..dcc5db519499 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -22,7 +22,10 @@ #include "zend_variables.h" #include "zend_API.h" #include "zend_objects_API.h" +#include "zend_exceptions.h" #include "zend_fibers.h" +#include "zend_weakrefs.h" +#include "zend_gc.h" ZEND_API void ZEND_FASTCALL zend_objects_store_init(zend_objects_store *objects, uint32_t init_size) { @@ -39,6 +42,346 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_destroy(zend_objects_store *objec objects->object_buckets = NULL; } +ZEND_API void ZEND_FASTCALL zend_defer_dtor(zend_object *object) +{ + zend_dtor_buf *buf = &EG(deferred_dtors); + zend_function *destructor = object->ce->destructor; + + ZEND_ASSERT(GC_REFCOUNT(object) == 0); + GC_ADDREF(object); + OBJ_EXTRA_FLAGS(object) |= IS_OBJ_DTOR_PENDING; + if (destructor + && UNEXPECTED(destructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) + && !zend_check_method_accessible(destructor, zend_get_executed_scope())) { + OBJ_EXTRA_FLAGS(object) |= IS_OBJ_DTOR_VIS_FAIL; + } + GC_REMOVE_FROM_BUFFER(object); + + if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) { + zend_weakrefs_notify_detach(object); + } + + if (UNEXPECTED(buf->count == buf->capacity)) { + uint32_t capacity = buf->capacity ? buf->capacity + (buf->capacity >> 1) : 8; + buf->objects = erealloc(buf->objects, sizeof(zend_object*) * capacity); + buf->capacity = capacity; + } + buf->objects[buf->count++] = object; + + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); +} + +static zend_always_inline void zend_dtor_flush_stash_exception(zend_object **pending, const zend_op **first_throw_opline) +{ + if (UNEXPECTED(EG(exception))) { + if (*pending) { + if (zend_is_unwind_exit(*pending) || zend_is_graceful_exit(*pending)) { + OBJ_RELEASE(EG(exception)); + EG(exception) = NULL; + return; + } + if (zend_is_unwind_exit(EG(exception)) || zend_is_graceful_exit(EG(exception))) { + OBJ_RELEASE(*pending); + } else { + zend_exception_set_previous(EG(exception), *pending); + } + } + *pending = EG(exception); + EG(exception) = NULL; + if (!*first_throw_opline) { + *first_throw_opline = EG(opline_before_exception); + } + } +} + +static zend_always_inline bool zend_dtor_flush_get_op_num( + const zend_op_array *op_array, const zend_op *opline, uint32_t *op_num) +{ + if (!opline || (uintptr_t) opline < (uintptr_t) op_array->opcodes) { + return false; + } + + uintptr_t offset = (uintptr_t) opline - (uintptr_t) op_array->opcodes; + if (offset >= (uintptr_t) op_array->last * sizeof(zend_op) + || offset % sizeof(zend_op) != 0) { + return false; + } + + *op_num = offset / sizeof(zend_op); + return true; +} + +static zend_always_inline zend_execute_data *zend_dtor_flush_find_frame( + zend_execute_data *execute_data, const zend_op *opline, uint32_t *op_num) +{ + for (; execute_data; execute_data = execute_data->prev_execute_data) { + if (!execute_data->func + || !ZEND_USER_CODE(execute_data->func->common.type)) { + continue; + } + + if (zend_dtor_flush_get_op_num( + &execute_data->func->op_array, opline, op_num)) { + return execute_data; + } + } + + return NULL; +} + +static zend_always_inline bool zend_dtor_flush_exception_is_catchable( + zend_execute_data *execute_data, const zend_op *first_throw_opline, + const zend_op *flush_opline) +{ + uint32_t throw_op_num; + zend_execute_data *throw_frame = zend_dtor_flush_find_frame( + execute_data, first_throw_opline, &throw_op_num); + + if (!throw_frame) { + throw_frame = zend_dtor_flush_find_frame( + execute_data, flush_opline, &throw_op_num); + } + if (!throw_frame) { + for (zend_execute_data *ex = execute_data; ex; ex = ex->prev_execute_data) { + if (ex->func && ZEND_USER_CODE(ex->func->common.type) && ex->opline + && zend_dtor_flush_get_op_num(&ex->func->op_array, ex->opline, &throw_op_num)) { + throw_frame = ex; + break; + } + } + } + if (!throw_frame) { + return false; + } + + execute_data = throw_frame; + for (; execute_data; execute_data = execute_data->prev_execute_data) { + if (!execute_data->func + || !ZEND_USER_CODE(execute_data->func->common.type) + || !execute_data->opline) { + continue; + } + + const zend_op_array *op_array = &execute_data->func->op_array; + uint32_t op_num; + + if (execute_data == throw_frame) { + op_num = throw_op_num; + } else if (!zend_dtor_flush_get_op_num( + op_array, execute_data->opline, &op_num)) { + continue; + } + + const zend_op *opline = &op_array->opcodes[op_num]; + if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) + && (opline->extended_value & ZEND_FREE_ON_RETURN)) { + op_num += opline->op2.opline_num; + } + + for (uint32_t i = 0; i < op_array->last_try_catch; i++) { + const zend_try_catch_element *try_catch = &op_array->try_catch_array[i]; + + if (try_catch->try_op > op_num) { + break; + } + if (op_num < try_catch->catch_op || op_num < try_catch->finally_end) { + return true; + } + } + } + + return false; +} + +static zend_always_inline bool zend_dtor_flush_release_throw_operand_at( + zend_execute_data *execute_data, const zend_op *flush_opline) +{ + uint32_t op_num; + zend_execute_data *frame = zend_dtor_flush_find_frame( + execute_data, flush_opline, &op_num); + + if (!frame) { + return false; + } + + const zend_op_array *op_array = &frame->func->op_array; + if (op_num + 1 >= op_array->last + || op_array->opcodes[op_num].opcode != ZEND_FLUSH_DEFERRED_DTORS) { + return false; + } + + const zend_op *throw_op = &op_array->opcodes[op_num + 1]; + if (throw_op->opcode != ZEND_THROW) { + return false; + } + + if (throw_op->op1_type & (IS_TMP_VAR | IS_VAR)) { + zval *operand = ZEND_CALL_VAR(frame, throw_op->op1.var); + + EG(frame_teardown)++; + zval_ptr_dtor_nogc(operand); + EG(frame_teardown)--; + ZVAL_UNDEF(operand); + } + + return true; +} + +static zend_always_inline void zend_dtor_flush_release_throw_operand( + zend_execute_data *execute_data, const zend_op *first_throw_opline, + const zend_op *flush_opline) +{ + if (zend_dtor_flush_release_throw_operand_at( + execute_data, first_throw_opline)) { + return; + } + + zend_dtor_flush_release_throw_operand_at( + execute_data, flush_opline); +} + +static zend_always_inline void zend_flush_deferred_dtors_ex(bool surface_uncatchable) +{ + zend_dtor_buf *buf = &EG(deferred_dtors); + zend_execute_data *execute_data = EG(current_execute_data); + const zend_op *flush_opline = execute_data && execute_data->func + && ZEND_USER_CODE(execute_data->func->common.type) ? execute_data->opline : NULL; + const zend_op *saved_opline_before_exception = EG(opline_before_exception); + zend_object *pending = EG(exception); + const zend_op *first_throw_opline = NULL; + bool had_exception = pending != NULL; + bool opline_rewound = false; + + if (UNEXPECTED(pending != NULL)) { + EG(exception) = NULL; + if (flush_opline == EG(exception_op) + && saved_opline_before_exception) { + execute_data->opline = saved_opline_before_exception; + opline_rewound = true; + } + } + + EG(frame_teardown)++; + while (buf->count || buf->values_count) { + zend_dtor_buf batch = *buf; + memset(buf, 0, sizeof(*buf)); + + for (uint32_t i = 0; i < batch.count; i++) { + zend_object *object = batch.objects[i]; + OBJ_RELEASE(object); + zend_dtor_flush_stash_exception(&pending, &first_throw_opline); + } + if (batch.objects) { + efree(batch.objects); + } + + for (uint32_t j = 0; j < batch.values_count; j++) { + zval_ptr_dtor(&batch.values[j]); + zend_dtor_flush_stash_exception(&pending, &first_throw_opline); + } + if (batch.values) { + efree(batch.values); + } + } + EG(frame_teardown)--; + + if (opline_rewound) { + execute_data->opline = EG(exception_op); + } + + if (EXPECTED(pending == NULL)) { + return; + } + + bool catchable = !had_exception + && zend_dtor_flush_exception_is_catchable( + execute_data, first_throw_opline, flush_opline); + + if (had_exception + || catchable + || surface_uncatchable + || zend_is_unwind_exit(pending) + || zend_is_graceful_exit(pending)) { + zend_execute_data *ex = EG(current_execute_data); + + EG(exception) = pending; + if (had_exception) { + EG(opline_before_exception) = saved_opline_before_exception; + } else if (first_throw_opline + && ex && ex->func && ZEND_USER_CODE(ex->func->common.type) + && ex->opline == EG(exception_op)) { + EG(opline_before_exception) = first_throw_opline; + } + + zend_dtor_flush_release_throw_operand( + execute_data, first_throw_opline, flush_opline); + return; + } + + if (EG(deferred_dtor_exception)) { + zend_object *previous = EG(deferred_dtor_exception); + EG(deferred_dtor_exception) = NULL; + zend_exception_set_previous(pending, previous); + } + EG(deferred_dtor_exception) = pending; + + if (flush_opline && execute_data->opline == EG(exception_op)) { + execute_data->opline = flush_opline; + } + EG(opline_before_exception) = saved_opline_before_exception; +} + +ZEND_API void ZEND_FASTCALL zend_flush_deferred_dtors(void) +{ + zend_flush_deferred_dtors_ex(false); +} + +ZEND_API void ZEND_FASTCALL zend_flush_deferred_dtors_surface(void) +{ + zend_flush_deferred_dtors_ex(true); +} + +ZEND_API void ZEND_FASTCALL zend_surface_deferred_dtor_exception(void) +{ + zend_object *exception = EG(deferred_dtor_exception); + + if (!exception) { + return; + } + if (EG(exception) + && (zend_is_unwind_exit(EG(exception)) || zend_is_graceful_exit(EG(exception)))) { + return; + } + + EG(deferred_dtor_exception) = NULL; + if (EG(exception)) { + zend_exception_set_previous(EG(exception), exception); + } else { + EG(exception) = exception; + } +} + +ZEND_API void ZEND_FASTCALL zend_release_deferred_dtors(void) +{ + zend_dtor_buf *buf = &EG(deferred_dtors); + + for (uint32_t i = 0; i < buf->count; i++) { + zend_object *object = buf->objects[i]; + OBJ_EXTRA_FLAGS(object) &= ~(IS_OBJ_DTOR_PENDING|IS_OBJ_DTOR_VIS_FAIL); + GC_DELREF(object); + } + for (uint32_t i = 0; i < buf->values_count; i++) { + zval_ptr_dtor(&buf->values[i]); + } + if (buf->objects) { + efree(buf->objects); + } + if (buf->values) { + efree(buf->values); + } + memset(buf, 0, sizeof(*buf)); +} + ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_store *objects) { EG(flags) |= EG_FLAGS_OBJECT_STORE_NO_REUSE; @@ -156,6 +499,45 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_put(zend_object *object) EG(objects_store).object_buckets[handle] = object; } +static zend_always_inline bool zend_can_defer_dtor(zend_object *object) +{ + if (!EG(dtor_defer_gate) || EG(frame_teardown)) { + return false; + } + if (OBJ_EXTRA_FLAGS(object) & IS_OBJ_DTOR_PENDING) { + return false; + } + if (CG(in_compilation) || !EG(current_execute_data) || !EG(current_execute_data)->func) { + return false; + } + zend_execute_data *ex = EG(current_execute_data); + if (!ZEND_USER_CODE(ex->func->type) || !ex->opline) { + return false; + } + switch (ex->opline->opcode) { + case ZEND_DECLARE_CLASS: + case ZEND_DECLARE_CLASS_DELAYED: + case ZEND_DECLARE_ANON_CLASS: + case ZEND_INIT_FCALL: + case ZEND_INIT_FCALL_BY_NAME: + case ZEND_INIT_NS_FCALL_BY_NAME: + case ZEND_INIT_METHOD_CALL: + case ZEND_INIT_STATIC_METHOD_CALL: + case ZEND_INIT_USER_CALL: + case ZEND_INIT_DYNAMIC_CALL: + case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL: + case ZEND_DO_FCALL: + case ZEND_DO_FCALL_BY_NAME: + case ZEND_DO_UCALL: + case ZEND_DO_ICALL: + case ZEND_FETCH_CONSTANT: + case ZEND_FETCH_CLASS_CONSTANT: + case ZEND_INCLUDE_OR_EVAL: + return false; + } + return true; +} + ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ */ { ZEND_ASSERT(GC_REFCOUNT(object) == 0); @@ -165,15 +547,24 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ * return; } - /* Make sure we hold a reference count during the destructor call - otherwise, when the destructor ends the storage might be freed - when the refcount reaches 0 a second time - */ if (!(OBJ_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) { + bool has_dtor = object->handlers->dtor_obj != zend_objects_destroy_object + || object->ce->destructor; + + if (has_dtor + && zend_can_defer_dtor(object) + && !zend_gc_is_condemned((zend_refcounted*)object)) { + zend_defer_dtor(object); + return; + } + + /* Make sure we hold a reference count during the destructor call + otherwise, when the destructor ends the storage might be freed + when the refcount reaches 0 a second time + */ GC_ADD_FLAGS(object, IS_OBJ_DESTRUCTOR_CALLED); - if (object->handlers->dtor_obj != zend_objects_destroy_object - || object->ce->destructor) { + if (has_dtor) { GC_SET_REFCOUNT(object, 1); object->handlers->dtor_obj(object); GC_DELREF(object); diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index 434ac4499e7f..2a5bc8dad426 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -62,6 +62,12 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_destroy(zend_objects_store *objec ZEND_API void ZEND_FASTCALL zend_objects_store_put(zend_object *object); ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object); +ZEND_API void ZEND_FASTCALL zend_defer_dtor(zend_object *object); +ZEND_API void ZEND_FASTCALL zend_flush_deferred_dtors(void); +ZEND_API void ZEND_FASTCALL zend_flush_deferred_dtors_surface(void); +ZEND_API void ZEND_FASTCALL zend_surface_deferred_dtor_exception(void); +ZEND_API void ZEND_FASTCALL zend_release_deferred_dtors(void); + /* Called when the ctor was terminated by an exception */ static zend_always_inline void zend_object_store_ctor_failed(zend_object *obj) { diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 56774e4e9d8f..5e630faa28a8 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -943,6 +943,8 @@ static zend_always_inline uint32_t zend_gc_delref_ex(zend_refcounted_h *p, uint3 #define IS_OBJ_LAZY_UNINITIALIZED (1U<<31) /* Virtual proxy or uninitialized Ghost */ #define IS_OBJ_LAZY_PROXY (1U<<30) /* Virtual proxy (may be initialized) */ +#define IS_OBJ_DTOR_PENDING (1U<<29) /* Destructor deferred to the next VM safepoint */ +#define IS_OBJ_DTOR_VIS_FAIL (1U<<28) /* Deferred destructor inaccessible from the drop-site scope */ #define OBJ_EXTRA_FLAGS(obj) ((obj)->extra_flags) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ec9a97eeb254..3622bd8d9019 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2992,8 +2992,13 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) SAVE_OPLINE(); #endif + if (UNEXPECTED(EG(deferred_errors).size)) { + zend_flush_deferred_errors(); + } + if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -3004,6 +3009,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); @@ -3016,6 +3022,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) ZEND_VM_LEAVE(); } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -3038,6 +3045,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; old_execute_data = execute_data; execute_data = EX(prev_execute_data); @@ -3055,8 +3063,10 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) zend_detach_symbol_table(execute_data); call_info |= ZEND_CALL_NEEDS_REATTACH; } + EG(frame_teardown)++; zend_destroy_static_vars(&EX(func)->op_array); destroy_op_array(&EX(func)->op_array); + EG(frame_teardown)--; efree_size(EX(func), sizeof(zend_op_array)); old_execute_data = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); @@ -3079,6 +3089,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) } else { if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD call_info = EX_CALL_INFO(); @@ -3095,6 +3106,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -3277,6 +3289,13 @@ ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, LOOP_END) SAVE_OPLINE(); FREE_OP1(); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -3292,6 +3311,13 @@ ZEND_VM_HOT_HANDLER(127, ZEND_FE_FREE, TMPVAR, LOOP_END) zend_hash_iterator_del(Z_FE_ITER_P(var)); } zval_ptr_dtor_nogc(var); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -3300,6 +3326,13 @@ ZEND_VM_HOT_HANDLER(127, ZEND_FE_FREE, TMPVAR, LOOP_END) if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(var)); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); @@ -4145,6 +4178,15 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + ZEND_VM_C_GOTO(icall_skip); + } + } + ZEND_OBSERVER_FCALL_BEGIN(call); fbc->internal_function.handler(call, ret); @@ -4167,6 +4209,7 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +ZEND_VM_C_LABEL(icall_skip): EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -4278,6 +4321,15 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER)) ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + ZEND_VM_C_GOTO(fcall_by_name_skip); + } + } + ZEND_OBSERVER_FCALL_BEGIN(call); fbc->internal_function.handler(call, ret); @@ -4301,6 +4353,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER)) ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +ZEND_VM_C_LABEL(fcall_by_name_skip): EG(current_execute_data) = execute_data; ZEND_VM_C_GOTO(fcall_by_name_end); @@ -4406,6 +4459,15 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + ZEND_VM_C_GOTO(fcall_skip); + } + } + ZEND_OBSERVER_FCALL_BEGIN(call); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -4434,6 +4496,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +ZEND_VM_C_LABEL(fcall_skip): EG(current_execute_data) = execute_data; ZEND_VM_C_GOTO(fcall_end); @@ -4775,6 +4838,13 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + FREE_OP1(); + HANDLE_EXCEPTION(); + } + } retval = GET_OP1_ZVAL_PTR(BP_VAR_R); /* Copy return value into generator->retval */ @@ -8179,7 +8249,9 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) { zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); + EG(frame_teardown)++; zval_ptr_dtor(return_value); + EG(frame_teardown)--; } /* Chain potential exception from wrapping finally block */ @@ -8187,7 +8259,9 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca if (ex) { if (zend_is_unwind_exit(ex) || zend_is_graceful_exit(ex)) { /* discard the previously thrown exception */ + EG(frame_teardown)++; OBJ_RELEASE(Z_OBJ_P(fast_call)); + EG(frame_teardown)--; } else { zend_exception_set_previous(ex, Z_OBJ_P(fast_call)); } @@ -8223,6 +8297,28 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) { const zend_op *throw_op = EG(opline_before_exception); + if (EG(deferred_errors).size || EG(deferred_dtors).count || EG(deferred_dtors).values_count) { + zend_object *orig_exception = EG(exception); + EX(opline) = EG(opline_before_exception); + EG(exception) = NULL; + + zend_flush_deferred_dtors(); + zend_flush_deferred_errors(); + + if (EG(exception)) { + if (UNEXPECTED(zend_is_unwind_exit(orig_exception) || zend_is_graceful_exit(orig_exception))) { + OBJ_RELEASE(EG(exception)); + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } else { + zend_exception_set_previous(EG(exception), orig_exception); + } + } else { + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } + } + /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, op_num, 0); @@ -8450,6 +8546,16 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|CV|UNUSED, S ZEND_VM_DISPATCH_TO_HELPER(zend_yield_in_closed_generator_helper); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + FREE_OP2(); + FREE_OP1(); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -8576,6 +8682,15 @@ ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMP|CV, ANY) HANDLE_EXCEPTION(); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + FREE_OP1(); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + ZEND_VM_C_LABEL(yield_from_try_again): if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); @@ -8710,7 +8825,9 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH) if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1) { const zend_op *fast_ret = EX(func)->op_array.opcodes + Z_OPLINE_NUM_P(fast_call); - ZEND_VM_JMP_EX(fast_ret + 1, 0); + ZEND_VM_SET_OPCODE_NO_INTERRUPT(fast_ret + 1); + ZEND_VM_INTERRUPT_CHECK(); + ZEND_VM_CONTINUE(); } /* special case for unhandled exceptions */ @@ -8931,6 +9048,25 @@ ZEND_VM_HOT_HANDLER(211, ZEND_TYPE_ASSERT, CONST, ANY, NUM) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +ZEND_VM_HOT_HANDLER(212, ZEND_FLUSH_DEFERRED_DTORS, ANY, ANY) +{ + USE_OPLINE + + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + SAVE_OPLINE(); + if ((opline + 1)->opcode == ZEND_THROW) { + zend_flush_deferred_dtors_surface(); + } else { + zend_flush_deferred_dtors(); + } + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HOT_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT) { USE_OPLINE @@ -10635,23 +10771,30 @@ ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY) #endif if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); - } else if (zend_interrupt_function) { - zend_interrupt_function(execute_data); - if (EG(exception)) { - /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ - const zend_op *throw_op = EG(opline_before_exception); - - if (throw_op - && throw_op->result_type & (IS_TMP_VAR|IS_VAR) - && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT - && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK - && throw_op->opcode != ZEND_ROPE_INIT - && throw_op->opcode != ZEND_ROPE_ADD) { - ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); + } else if (zend_interrupt_process(execute_data, opline, false)) { + zend_interrupt_handle_exception(); + if (!zend_atomic_bool_load_ex(&EG(vm_interrupt))) { + ZEND_VM_ENTER(); + } + } + ZEND_VM_CONTINUE(); +} - } +ZEND_VM_HELPER(zend_loop_interrupt_helper, ANY, ANY) +{ + zend_atomic_bool_store_ex(&EG(vm_interrupt), false); +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + LOAD_OPLINE(); +#else + SAVE_OPLINE(); +#endif + if (zend_atomic_bool_load_ex(&EG(timed_out))) { + zend_timeout(); + } else if (zend_interrupt_process(execute_data, opline, true)) { + zend_interrupt_handle_exception(); + if (!zend_atomic_bool_load_ex(&EG(vm_interrupt))) { + ZEND_VM_ENTER(); } - ZEND_VM_ENTER(); } ZEND_VM_CONTINUE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 34b2455ce439..e353a0ecddb6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -433,7 +433,7 @@ static zend_vm_opcode_handler_func_t zend_vm_get_opcode_handler_func(uint8_t opc #if defined(ZEND_VM_FP_GLOBAL_REG) # define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE() # define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX() -# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE() +# define ZEND_VM_LEAVE() ZEND_VM_LOOP_INTERRUPT_CHECK(); ZEND_VM_CONTINUE() #elif defined(ZEND_VM_IP_GLOBAL_REG) # define ZEND_VM_ENTER_EX() return 1 # define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX() @@ -446,13 +446,14 @@ static zend_vm_opcode_handler_func_t zend_vm_get_opcode_handler_func(uint8_t opc #endif #define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); #ifdef ZEND_VM_FP_GLOBAL_REG -#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +#define ZEND_VM_LOOP_INTERRUPT() zend_loop_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #else -#define ZEND_VM_LOOP_INTERRUPT() opline = (zend_op*)((uintptr_t)zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) & ~ZEND_VM_ENTER_BIT); +#define ZEND_VM_LOOP_INTERRUPT() opline = (zend_op*)((uintptr_t)zend_loop_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) & ~ZEND_VM_ENTER_BIT); #endif #define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler_func(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_loop_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS); static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) @@ -1157,8 +1158,13 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV SAVE_OPLINE(); #endif + if (UNEXPECTED(EG(deferred_errors).size)) { + zend_flush_deferred_errors(); + } + if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -1169,6 +1175,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); @@ -1181,6 +1188,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_VM_LEAVE(); } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -1203,6 +1211,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; old_execute_data = execute_data; execute_data = EX(prev_execute_data); @@ -1220,8 +1229,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_detach_symbol_table(execute_data); call_info |= ZEND_CALL_NEEDS_REATTACH; } + EG(frame_teardown)++; zend_destroy_static_vars(&EX(func)->op_array); destroy_op_array(&EX(func)->op_array); + EG(frame_teardown)--; efree_size(EX(func), sizeof(zend_op_array)); old_execute_data = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); @@ -1244,6 +1255,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV } else { if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD call_info = EX_CALL_INFO(); @@ -1260,6 +1272,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -1318,6 +1331,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !0 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto icall_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -1341,6 +1363,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ZEND_VM_FCALL_INTERRUPT_CHECK(call); +icall_skip: EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -1388,6 +1411,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !1 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto icall_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -1411,6 +1443,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ZEND_VM_FCALL_INTERRUPT_CHECK(call); +icall_skip: EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -1458,6 +1491,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto icall_skip; + } + } + zend_observer_fcall_begin_specialized(call, false); fbc->internal_function.handler(call, ret); @@ -1480,6 +1522,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ zend_observer_fcall_end(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +icall_skip: EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -1644,6 +1687,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !0 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_by_name_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -1668,6 +1720,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_by_name_skip: EG(current_execute_data) = execute_data; goto fcall_by_name_end; @@ -1762,6 +1815,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !1 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_by_name_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -1786,6 +1848,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_by_name_skip: EG(current_execute_data) = execute_data; goto fcall_by_name_end; @@ -1879,6 +1942,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_by_name_skip; + } + } + zend_observer_fcall_begin_specialized(call, false); fbc->internal_function.handler(call, ret); @@ -1902,6 +1974,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ zend_observer_fcall_end(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_by_name_skip: EG(current_execute_data) = execute_data; goto fcall_by_name_end; @@ -2010,6 +2083,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !0 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_skip; + } + } + if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -2039,6 +2121,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_skip: EG(current_execute_data) = execute_data; goto fcall_end; @@ -2145,6 +2228,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !1 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_skip; + } + } + if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -2174,6 +2266,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_skip: EG(current_execute_data) = execute_data; goto fcall_end; @@ -2277,6 +2370,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_skip; + } + } + zend_observer_fcall_begin_specialized(call, false); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -2305,6 +2407,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ zend_observer_fcall_end(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_skip: EG(current_execute_data) = execute_data; goto fcall_end; @@ -3355,7 +3458,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_ && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) { zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); + EG(frame_teardown)++; zval_ptr_dtor(return_value); + EG(frame_teardown)--; } /* Chain potential exception from wrapping finally block */ @@ -3363,7 +3468,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_ if (ex) { if (zend_is_unwind_exit(ex) || zend_is_graceful_exit(ex)) { /* discard the previously thrown exception */ + EG(frame_teardown)++; OBJ_RELEASE(Z_OBJ_P(fast_call)); + EG(frame_teardown)--; } else { zend_exception_set_previous(ex, Z_OBJ_P(fast_call)); } @@ -3399,6 +3506,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_HANDLE_EXCEPT { const zend_op *throw_op = EG(opline_before_exception); + if (EG(deferred_errors).size || EG(deferred_dtors).count || EG(deferred_dtors).values_count) { + zend_object *orig_exception = EG(exception); + EX(opline) = EG(opline_before_exception); + EG(exception) = NULL; + + zend_flush_deferred_dtors(); + zend_flush_deferred_errors(); + + if (EG(exception)) { + if (UNEXPECTED(zend_is_unwind_exit(orig_exception) || zend_is_graceful_exit(orig_exception))) { + OBJ_RELEASE(EG(exception)); + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } else { + zend_exception_set_previous(EG(exception), orig_exception); + } + } else { + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } + } + /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); @@ -3547,7 +3676,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_RET_SPEC if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1) { const zend_op *fast_ret = EX(func)->op_array.opcodes + Z_OPLINE_NUM_P(fast_call); - ZEND_VM_JMP_EX(fast_ret + 1, 0); + ZEND_VM_SET_OPCODE_NO_INTERRUPT(fast_ret + 1); + ZEND_VM_INTERRUPT_CHECK(); + ZEND_VM_CONTINUE(); } /* special case for unhandled exceptions */ @@ -3558,6 +3689,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_RET_SPEC ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, current_op_num)); } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FLUSH_DEFERRED_DTORS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + SAVE_OPLINE(); + if ((opline + 1)->opcode == ZEND_THROW) { + zend_flush_deferred_dtors_surface(); + } else { + zend_flush_deferred_dtors(); + } + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4040,23 +4190,30 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV #endif if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); - } else if (zend_interrupt_function) { - zend_interrupt_function(execute_data); - if (EG(exception)) { - /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ - const zend_op *throw_op = EG(opline_before_exception); - - if (throw_op - && throw_op->result_type & (IS_TMP_VAR|IS_VAR) - && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT - && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK - && throw_op->opcode != ZEND_ROPE_INIT - && throw_op->opcode != ZEND_ROPE_ADD) { - ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); + } else if (zend_interrupt_process(execute_data, opline, false)) { + zend_interrupt_handle_exception(); + if (!zend_atomic_bool_load_ex(&EG(vm_interrupt))) { + ZEND_VM_ENTER(); + } + } + ZEND_VM_CONTINUE(); +} - } +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_loop_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_atomic_bool_store_ex(&EG(vm_interrupt), false); +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + LOAD_OPLINE(); +#else + SAVE_OPLINE(); +#endif + if (zend_atomic_bool_load_ex(&EG(timed_out))) { + zend_timeout(); + } else if (zend_interrupt_process(execute_data, opline, true)) { + zend_interrupt_handle_exception(); + if (!zend_atomic_bool_load_ex(&EG(vm_interrupt))) { + ZEND_VM_ENTER(); } - ZEND_VM_ENTER(); } ZEND_VM_CONTINUE(); } @@ -5042,6 +5199,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RET zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + HANDLE_EXCEPTION(); + } + } retval = RT_CONSTANT(opline, opline->op1); /* Copy return value into generator->retval */ @@ -5088,6 +5253,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RET zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } retval = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); /* Copy return value into generator->retval */ @@ -5959,6 +6131,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_FROM_SP HANDLE_EXCEPTION(); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); @@ -8371,6 +8553,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CO ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -10782,6 +10976,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CO ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -11667,6 +11872,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CO ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -13405,6 +13622,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CO ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -15613,6 +15842,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FREE_SPEC_TMP SAVE_OPLINE(); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -15628,6 +15864,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_F zend_hash_iterator_del(Z_FE_ITER_P(var)); } zval_ptr_dtor_nogc(var); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -15636,6 +15879,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_F if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(var)); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); @@ -17269,6 +17519,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RET zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ @@ -18049,6 +18306,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_FROM_SP HANDLE_EXCEPTION(); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + 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); @@ -19702,6 +19968,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TM ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -21189,6 +21466,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TM ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -21883,6 +22170,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TM ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -23057,6 +23355,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TM ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -23513,6 +23822,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RET zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ @@ -26380,6 +26696,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VA ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -28638,6 +28965,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VA ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -30278,6 +30615,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VA ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -32518,6 +32866,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VA ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -34761,6 +35120,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UN ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -36651,6 +37022,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UN ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -37200,6 +37582,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UN ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -39240,6 +39634,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UN ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -39945,6 +40351,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RET zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + HANDLE_EXCEPTION(); + } + } retval = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ @@ -40646,6 +41060,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_FROM_SP HANDLE_EXCEPTION(); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); @@ -44576,6 +45000,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -48188,6 +48624,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -49777,6 +50224,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -53365,6 +53824,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -53551,7 +54022,7 @@ static ZEND_COLD zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_F # define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE() # define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) # define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE() -# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE() +# define ZEND_VM_LEAVE() ZEND_VM_LOOP_INTERRUPT_CHECK(); ZEND_VM_CONTINUE() static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS); static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt(ZEND_OPCODE_HANDLER_ARGS); @@ -53962,8 +54433,13 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend SAVE_OPLINE(); #endif + if (UNEXPECTED(EG(deferred_errors).size)) { + zend_flush_deferred_errors(); + } + if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -53974,6 +54450,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); @@ -53986,6 +54463,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend ZEND_VM_LEAVE(); } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -54008,6 +54486,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; old_execute_data = execute_data; execute_data = EX(prev_execute_data); @@ -54025,8 +54504,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend zend_detach_symbol_table(execute_data); call_info |= ZEND_CALL_NEEDS_REATTACH; } + EG(frame_teardown)++; zend_destroy_static_vars(&EX(func)->op_array); destroy_op_array(&EX(func)->op_array); + EG(frame_teardown)--; efree_size(EX(func), sizeof(zend_op_array)); old_execute_data = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); @@ -54049,6 +54530,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend } else { if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD call_info = EX_CALL_INFO(); @@ -54065,6 +54547,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -54123,6 +54606,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !0 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto icall_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -54146,6 +54638,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA ZEND_VM_FCALL_INTERRUPT_CHECK(call); +icall_skip: EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -54193,6 +54686,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !1 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto icall_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -54216,6 +54718,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA ZEND_VM_FCALL_INTERRUPT_CHECK(call); +icall_skip: EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -54263,6 +54766,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_IC ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto icall_skip; + } + } + zend_observer_fcall_begin_specialized(call, false); fbc->internal_function.handler(call, ret); @@ -54285,6 +54797,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_IC zend_observer_fcall_end(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +icall_skip: EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -54449,6 +54962,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !0 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_by_name_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -54473,6 +54995,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_by_name_skip: EG(current_execute_data) = execute_data; goto fcall_by_name_end; @@ -54567,6 +55090,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !1 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_by_name_skip; + } + } + fbc->internal_function.handler(call, ret); @@ -54591,6 +55123,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_by_name_skip: EG(current_execute_data) = execute_data; goto fcall_by_name_end; @@ -54684,6 +55217,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FC ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_by_name_skip; + } + } + zend_observer_fcall_begin_specialized(call, false); fbc->internal_function.handler(call, ret); @@ -54707,6 +55249,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FC zend_observer_fcall_end(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_by_name_skip: EG(current_execute_data) = execute_data; goto fcall_by_name_end; @@ -54815,6 +55358,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !0 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_skip; + } + } + if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -54844,6 +55396,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_skip: EG(current_execute_data) = execute_data; goto fcall_end; @@ -54950,6 +55503,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !1 + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_skip; + } + } + if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -54979,6 +55541,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_skip: EG(current_execute_data) = execute_data; goto fcall_end; @@ -55082,6 +55645,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FC ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (UNEXPECTED((EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !RETURN_VALUE_USED(opline) + && !EX(call))) { + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + goto fcall_skip; + } + } + zend_observer_fcall_begin_specialized(call, false); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -55110,6 +55682,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FC zend_observer_fcall_end(call, EG(exception) ? NULL : ret); ZEND_VM_FCALL_INTERRUPT_CHECK(call); +fcall_skip: EG(current_execute_data) = execute_data; goto fcall_end; @@ -56088,6 +56661,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HANDLE_EXCEPTION_S { const zend_op *throw_op = EG(opline_before_exception); + if (EG(deferred_errors).size || EG(deferred_dtors).count || EG(deferred_dtors).values_count) { + zend_object *orig_exception = EG(exception); + EX(opline) = EG(opline_before_exception); + EG(exception) = NULL; + + zend_flush_deferred_dtors(); + zend_flush_deferred_errors(); + + if (EG(exception)) { + if (UNEXPECTED(zend_is_unwind_exit(orig_exception) || zend_is_graceful_exit(orig_exception))) { + OBJ_RELEASE(EG(exception)); + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } else { + zend_exception_set_previous(EG(exception), orig_exception); + } + } else { + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } + } + /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); @@ -56236,7 +56831,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_RET_SPEC_TAIL if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1) { const zend_op *fast_ret = EX(func)->op_array.opcodes + Z_OPLINE_NUM_P(fast_call); - ZEND_VM_JMP_EX(fast_ret + 1, 0); + ZEND_VM_SET_OPCODE_NO_INTERRUPT(fast_ret + 1); + ZEND_VM_INTERRUPT_CHECK(); + ZEND_VM_CONTINUE(); } /* special case for unhandled exceptions */ @@ -56247,6 +56844,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_RET_SPEC_TAIL ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, current_op_num)); } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FLUSH_DEFERRED_DTORS_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + SAVE_OPLINE(); + if ((opline + 1)->opcode == ZEND_THROW) { + zend_flush_deferred_dtors_surface(); + } else { + zend_flush_deferred_dtors(); + } + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSERT_CHECK_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -56729,26 +57345,15 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend #endif if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); - } else if (zend_interrupt_function) { - zend_interrupt_function(execute_data); - if (EG(exception)) { - /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ - const zend_op *throw_op = EG(opline_before_exception); - - if (throw_op - && throw_op->result_type & (IS_TMP_VAR|IS_VAR) - && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT - && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK - && throw_op->opcode != ZEND_ROPE_INIT - && throw_op->opcode != ZEND_ROPE_ADD) { - ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); - - } + } else if (zend_interrupt_process(execute_data, opline, false)) { + zend_interrupt_handle_exception(); + if (!zend_atomic_bool_load_ex(&EG(vm_interrupt))) { + ZEND_VM_ENTER(); } - ZEND_VM_ENTER(); } ZEND_VM_CONTINUE(); } + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -57731,6 +58336,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_S zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + HANDLE_EXCEPTION(); + } + } retval = RT_CONSTANT(opline, opline->op1); /* Copy return value into generator->retval */ @@ -57777,6 +58390,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_S zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } retval = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); /* Copy return value into generator->retval */ @@ -58648,6 +59268,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_FROM_SPEC_CO HANDLE_EXCEPTION(); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); @@ -61060,6 +61690,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_C ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -63471,6 +64113,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_T ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -64254,6 +64907,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_U ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -65992,6 +66657,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_C ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -68200,6 +68877,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FREE_SPEC_TMPVAR_T SAVE_OPLINE(); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -68215,6 +68899,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_FRE zend_hash_iterator_del(Z_FE_ITER_P(var)); } zval_ptr_dtor_nogc(var); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -68223,6 +68914,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_FRE if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(var)); + if (UNEXPECTED((opline->extended_value & ZEND_FREE_ON_RETURN) + && (EG(deferred_dtors).count || EG(deferred_dtors).values_count))) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); @@ -69856,6 +70554,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_S zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ @@ -70636,6 +71341,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_FROM_SPEC_TM HANDLE_EXCEPTION(); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + 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); @@ -72289,6 +73003,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_CON ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -73776,6 +74501,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_TMP ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -74370,6 +75105,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_UNU ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -75544,6 +76290,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_CV_ ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -76000,6 +76757,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_S zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ @@ -78867,6 +79631,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_CON ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -81125,6 +81900,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_TMP ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -82765,6 +83550,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_UNU ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -85005,6 +85801,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_CV_ ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -87248,6 +88055,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_ ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -89138,6 +89957,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_ ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -89687,6 +90517,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_ ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -91727,6 +92569,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_ ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -92432,6 +93286,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_S zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + HANDLE_EXCEPTION(); + } + } retval = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ @@ -93133,6 +93995,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_FROM_SPEC_CV HANDLE_EXCEPTION(); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); @@ -97063,6 +97935,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_CONS ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -100675,6 +101559,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_TMP_ ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -102162,6 +103057,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_UNUS ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -105750,6 +106657,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_CV_T ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + + + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + /* Destroy the previously yielded value */ zval_ptr_dtor(&generator->value); @@ -106319,7 +107238,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX z && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) { zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); + EG(frame_teardown)++; zval_ptr_dtor(return_value); + EG(frame_teardown)--; } /* Chain potential exception from wrapping finally block */ @@ -106327,7 +107248,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX z if (ex) { if (zend_is_unwind_exit(ex) || zend_is_graceful_exit(ex)) { /* discard the previously thrown exception */ + EG(frame_teardown)++; OBJ_RELEASE(Z_OBJ_P(fast_call)); + EG(frame_teardown)--; } else { zend_exception_set_previous(ex, Z_OBJ_P(fast_call)); } @@ -109273,6 +110196,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_TYPE_ASSERT_SPEC_CONST_LABEL, + (void*)&&ZEND_FLUSH_DEFERRED_DTORS_SPEC_LABEL, (void*)&&ZEND_INIT_FCALL_OFFSET_SPEC_CONST_LABEL, (void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -110304,8 +111228,13 @@ ZEND_API void execute_ex(zend_execute_data *ex) SAVE_OPLINE(); #endif + if (UNEXPECTED(EG(deferred_errors).size)) { + zend_flush_deferred_errors(); + } + if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -110316,6 +111245,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); @@ -110328,6 +111258,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_VM_LEAVE(); } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD @@ -110350,6 +111281,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; old_execute_data = execute_data; execute_data = EX(prev_execute_data); @@ -110367,8 +111299,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) zend_detach_symbol_table(execute_data); call_info |= ZEND_CALL_NEEDS_REATTACH; } + EG(frame_teardown)++; zend_destroy_static_vars(&EX(func)->op_array); destroy_op_array(&EX(func)->op_array); + EG(frame_teardown)--; efree_size(EX(func), sizeof(zend_op_array)); old_execute_data = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); @@ -110391,6 +111325,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) { EG(current_execute_data) = EX(prev_execute_data); + EG(frame_teardown)++; i_free_compiled_variables(execute_data); #ifdef ZEND_PREFER_RELOAD call_info = EX_CALL_INFO(); @@ -110407,6 +111342,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(frame_teardown)--; ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -110607,6 +111543,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_FAST_RET_SPEC) HYBRID_BREAK(); + HYBRID_CASE(ZEND_FLUSH_DEFERRED_DTORS_SPEC): + VM_TRACE(ZEND_FLUSH_DEFERRED_DTORS_SPEC) + ZEND_FLUSH_DEFERRED_DTORS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FLUSH_DEFERRED_DTORS_SPEC) + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSERT_CHECK_SPEC): VM_TRACE(ZEND_ASSERT_CHECK_SPEC) ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -118211,6 +119152,7 @@ void zend_vm_init(void) ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER, ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_HANDLER, ZEND_TYPE_ASSERT_SPEC_CONST_HANDLER, + ZEND_FLUSH_DEFERRED_DTORS_SPEC_HANDLER, ZEND_INIT_FCALL_OFFSET_SPEC_CONST_HANDLER, ZEND_RECV_NOTYPE_SPEC_HANDLER, ZEND_NULL_HANDLER, @@ -121689,6 +122631,7 @@ void zend_vm_init(void) ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_TAILCALL_HANDLER, ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_TAILCALL_HANDLER, ZEND_TYPE_ASSERT_SPEC_CONST_TAILCALL_HANDLER, + ZEND_FLUSH_DEFERRED_DTORS_SPEC_TAILCALL_HANDLER, ZEND_INIT_FCALL_OFFSET_SPEC_CONST_TAILCALL_HANDLER, ZEND_RECV_NOTYPE_SPEC_TAILCALL_HANDLER, ZEND_NULL_TAILCALL_HANDLER, @@ -122657,7 +123600,7 @@ void zend_vm_init(void) 1255, 1256 | SPEC_RULE_OP1, 1261 | SPEC_RULE_OP1, - 3474, + 3475, 1266 | SPEC_RULE_OP1, 1271 | SPEC_RULE_OP1, 1276 | SPEC_RULE_OP2, @@ -122691,7 +123634,7 @@ void zend_vm_init(void) 1559 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1584 | SPEC_RULE_OP1, 1589, - 3474, + 3475, 1590 | SPEC_RULE_OP1, 1595 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1620 | SPEC_RULE_OP1 | SPEC_RULE_OP2, @@ -122824,50 +123767,50 @@ void zend_vm_init(void) 2556, 2557, 2558, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, - 3474, + 2559, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, + 3475, }; #if 0 #elif (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) @@ -123060,7 +124003,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2567 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2568 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -123068,7 +124011,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2592 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2593 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -123076,7 +124019,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2617 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2618 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -123087,17 +124030,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2642 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2643 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2667 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2668 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } 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 = 2692 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2693 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -123108,17 +124051,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2717 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2718 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2742 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2743 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | 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 = 2767 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2768 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_IDENTICAL: @@ -123129,16 +124072,16 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2792 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2793 | 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 = 2867 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2868 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op2_type == IS_CONST && (Z_TYPE_P(RT_CONSTANT(op, op->op2)) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(RT_CONSTANT(op, op->op2))) == 0)) { - spec = 3092 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3093 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3098 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3099 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_IDENTICAL: @@ -123149,16 +124092,16 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2942 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2943 | 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 = 3017 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3018 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op2_type == IS_CONST && (Z_TYPE_P(RT_CONSTANT(op, op->op2)) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(RT_CONSTANT(op, op->op2))) == 0)) { - spec = 3095 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3096 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3103 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3104 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_EQUAL: @@ -123169,12 +124112,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2792 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2793 | 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 = 2867 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2868 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_EQUAL: @@ -123185,12 +124128,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2942 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2943 | 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 = 3017 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3018 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_SMALLER: @@ -123198,12 +124141,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3108 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3109 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } 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 = 3183 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3184 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -123211,79 +124154,79 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3258 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3259 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } 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 = 3333 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3334 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if (op1_info == MAY_BE_LONG) { - spec = 3420 | SPEC_RULE_OP1; + spec = 3421 | SPEC_RULE_OP1; } else if (op1_info == MAY_BE_DOUBLE) { - spec = 3425 | SPEC_RULE_OP1; + spec = 3426 | SPEC_RULE_OP1; } else if ((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))))) { - spec = 3430 | SPEC_RULE_OP1; + spec = 3431 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3408 | SPEC_RULE_RETVAL; + spec = 3409 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3410 | SPEC_RULE_RETVAL; + spec = 3411 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3412 | SPEC_RULE_RETVAL; + spec = 3413 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3414 | SPEC_RULE_RETVAL; + spec = 3415 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3416; - } else if (op1_info == MAY_BE_LONG) { spec = 3417; + } else if (op1_info == MAY_BE_LONG) { + spec = 3418; } break; case ZEND_POST_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3418; - } else if (op1_info == MAY_BE_LONG) { spec = 3419; + } else if (op1_info == MAY_BE_LONG) { + spec = 3420; } break; case ZEND_JMP: if (OP_JMP_ADDR(op, op->op1) > op) { - spec = 2566; + spec = 2567; } break; case ZEND_INIT_FCALL: if (Z_EXTRA_P(RT_CONSTANT(op, op->op2)) != 0) { - spec = 2559; + spec = 2560; } break; case ZEND_RECV: if (op->op2.num == MAY_BE_ANY) { - spec = 2560; + spec = 2561; } break; case ZEND_SEND_VAL: if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3470; + spec = 3471; } break; case ZEND_SEND_VAR_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3465 | SPEC_RULE_OP1; + spec = 3466 | SPEC_RULE_OP1; } break; case ZEND_FE_FETCH_R: if (op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 3472 | SPEC_RULE_RETVAL; + spec = 3473 | SPEC_RULE_RETVAL; } break; case ZEND_FETCH_DIM_R: @@ -123291,22 +124234,22 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3435 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3436 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_SEND_VAL_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3471; + spec = 3472; } break; case ZEND_SEND_VAR: if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3460 | SPEC_RULE_OP1; + spec = 3461 | SPEC_RULE_OP1; } break; case ZEND_COUNT: if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 2561 | SPEC_RULE_OP1; + spec = 2562 | SPEC_RULE_OP1; } break; case ZEND_BW_OR: diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 8e65bc0a28ea..288e8b008ff9 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -1145,6 +1145,13 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, return; } + /* zend_loop_interrupt_helper is only ever reached through the + * ZEND_VM_LOOP_INTERRUPT macro, which calls its non-tailcall function + * variant. A TAILCALL variant would be an unused static function. */ + if ($kind == ZEND_VM_KIND_TAILCALL && $name === 'zend_loop_interrupt_helper') { + return; + } + if ($spec && skip_extra_spec_function($op1, $op2, $extra_spec)) { return; } @@ -2029,7 +2036,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG)\n"); out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n"); - out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_LEAVE() ZEND_VM_LOOP_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"#elif defined(ZEND_VM_IP_GLOBAL_REG)\n"); out($f,"# define ZEND_VM_ENTER_EX() return 1\n"); out($f,"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()\n"); @@ -2042,9 +2049,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#endif\n"); out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n"); - out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_loop_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); out($f,"#else\n"); - out($f,"#define ZEND_VM_LOOP_INTERRUPT() opline = (zend_op*)((uintptr_t)zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) & ~ZEND_VM_ENTER_BIT);\n"); + out($f,"#define ZEND_VM_LOOP_INTERRUPT() opline = (zend_op*)((uintptr_t)zend_loop_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) & ~ZEND_VM_ENTER_BIT);\n"); out($f,"#endif\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler_func(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); @@ -2053,6 +2060,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) } out($f,"\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_loop_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n"); out($f,"\n"); break; @@ -2076,9 +2084,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n"); - out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_LEAVE() ZEND_VM_LOOP_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n"); - out($f,"#define ZEND_VM_LOOP_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n"); + out($f,"#define ZEND_VM_LOOP_INTERRUPT() goto zend_loop_interrupt_helper".($spec?"_SPEC":"").";\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n"); out($f,"\n"); break; @@ -2107,9 +2115,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n"); - out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_LEAVE() ZEND_VM_LOOP_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n"); - out($f,"#define ZEND_VM_LOOP_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n"); + out($f,"#define ZEND_VM_LOOP_INTERRUPT() goto zend_loop_interrupt_helper".($spec?"_SPEC":"").";\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n"); out($f,"\n"); break; @@ -2158,7 +2166,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"# define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n"); out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); - out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_LEAVE() ZEND_VM_LOOP_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); out($f,"\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS);\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt(ZEND_OPCODE_HANDLER_ARGS);\n"); diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 6f1595195450..ede0b8cc7e87 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1087,507 +1087,508 @@ _(2556, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED) \ _(2557, ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST) \ _(2558, ZEND_TYPE_ASSERT_SPEC_CONST) \ - _(2559, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \ - _(2560, ZEND_RECV_NOTYPE_SPEC) \ - _(2562, ZEND_COUNT_ARRAY_SPEC_TMP_UNUSED) \ - _(2565, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ - _(2566, ZEND_JMP_FORWARD_SPEC) \ - _(2572, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2573, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2559, ZEND_FLUSH_DEFERRED_DTORS_SPEC) \ + _(2560, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \ + _(2561, ZEND_RECV_NOTYPE_SPEC) \ + _(2563, ZEND_COUNT_ARRAY_SPEC_TMP_UNUSED) \ + _(2566, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ + _(2567, ZEND_JMP_FORWARD_SPEC) \ + _(2573, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2574, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2576, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2577, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2578, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2575, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2577, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2578, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2579, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2581, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2587, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2588, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2580, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2582, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2588, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2589, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2591, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2597, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2598, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2590, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2592, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2598, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2599, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2601, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2602, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2603, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2600, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2602, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2603, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2604, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2606, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2612, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2613, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2605, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2607, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2613, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2614, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2616, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2622, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2623, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2615, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2617, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2623, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2624, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2626, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2627, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2628, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2625, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2627, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2628, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2629, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2631, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2637, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2638, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2630, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2632, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2638, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2639, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2641, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2643, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2640, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2642, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2644, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2646, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2647, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2648, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2645, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2647, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2648, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2649, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2651, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2652, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2653, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2650, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2652, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2653, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2654, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2656, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2662, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2663, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2655, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2657, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2663, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2664, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2666, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2668, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2665, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2667, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2669, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2671, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2672, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2673, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2670, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2672, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2673, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2674, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2676, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2677, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2678, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2675, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2677, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2678, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2679, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2681, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2687, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2688, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2680, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2682, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2688, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2689, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2691, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2693, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2690, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2692, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2694, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2696, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2697, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2698, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2695, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2697, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2698, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2699, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2701, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2702, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2703, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2700, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2702, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2703, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2704, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2706, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2712, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2713, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2705, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2707, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2713, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2714, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2716, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2722, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2723, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2715, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2717, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2723, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2724, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2726, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2727, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2728, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2725, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2727, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2728, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2729, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2731, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2737, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2738, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2730, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2732, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2738, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2739, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2741, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2747, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2748, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2740, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2742, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2748, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2749, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2751, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2752, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2753, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2750, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2752, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2753, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2754, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2756, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2762, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2763, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2755, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2757, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2763, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2764, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2766, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2772, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2773, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2765, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2767, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2773, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2774, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2776, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2777, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2778, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2775, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2777, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2778, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2779, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2781, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2787, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2788, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2780, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2782, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2788, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2789, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2791, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2807, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2808, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2809, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2810, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2811, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2812, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2813, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2814, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2815, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2819, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2820, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2821, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2822, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2823, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2824, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2825, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2826, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2829, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2830, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2834, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2835, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2836, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2852, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2853, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2854, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2855, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2856, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2857, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2858, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2859, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2860, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2864, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2865, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2866, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2882, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2883, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2884, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2885, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2886, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2887, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2888, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2889, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2890, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2894, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2895, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2896, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2897, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2898, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2899, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2900, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2901, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2904, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2905, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2909, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2910, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2911, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2927, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2928, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2929, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2930, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2931, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2932, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2933, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2934, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2935, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2939, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2940, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2941, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2957, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2958, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2959, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2960, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2961, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2962, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2963, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2964, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2965, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2969, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2970, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2971, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2972, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2973, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2974, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2975, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2976, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2979, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2980, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2984, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2985, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2986, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3002, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3003, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3004, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3005, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3006, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3007, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3008, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3009, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3010, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3014, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3015, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3016, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3032, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3033, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3034, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3035, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3036, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3037, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3038, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3039, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3040, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3044, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3045, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3046, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3047, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3048, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3049, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3050, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3051, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3054, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3055, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3059, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3060, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3061, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3077, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3078, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3079, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3080, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3081, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3082, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3083, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3084, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3085, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3089, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3090, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3091, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3092, ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST) \ - _(3093, ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3094, ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3095, ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST) \ - _(3096, ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3097, ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3098, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3102, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3103, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3107, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3111, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3112, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3113, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3114, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3115, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3116, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3120, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3121, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3122, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3123, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3124, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3125, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3126, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3127, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3128, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3129, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3130, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3131, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3135, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3136, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3139, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3140, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3141, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3145, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3146, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3168, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3169, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3170, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3171, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3172, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3173, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3174, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3175, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3176, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3180, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3181, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3186, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3187, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3188, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3189, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3190, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3191, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3195, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3196, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3197, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3198, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3204, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3205, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3206, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3210, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3211, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3214, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3215, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3216, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3220, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3221, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3243, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3244, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3245, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3246, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3247, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3248, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3249, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3250, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3251, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3255, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3256, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3261, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3262, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3263, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3264, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3265, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3266, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3270, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3271, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3272, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3273, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3279, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3280, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3281, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3285, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3286, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3289, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3290, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3291, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3295, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3296, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3318, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3319, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3320, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3321, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3322, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3323, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3324, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3325, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3326, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3330, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3331, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3336, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3337, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3338, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3339, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3340, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3341, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3345, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3346, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3347, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3348, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3354, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3355, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3356, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3360, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3361, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3364, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3365, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3366, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3370, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3371, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3393, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3394, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3395, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3396, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3397, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3398, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3399, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3400, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3401, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3405, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3406, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3408, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3409, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3410, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3411, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ - _(3412, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3413, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3414, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3415, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ - _(3416, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3417, ZEND_POST_INC_LONG_SPEC_CV) \ - _(3418, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3419, ZEND_POST_DEC_LONG_SPEC_CV) \ - _(3420, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ - _(3421, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(2790, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2792, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2808, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2809, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2810, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2811, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2812, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2813, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2814, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2815, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2816, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2820, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2821, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2822, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2823, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2824, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2825, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2826, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2829, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2830, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2831, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2835, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2836, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2853, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2854, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2855, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2856, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2857, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2858, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2859, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2860, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2861, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2865, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2866, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2867, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2883, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2884, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2885, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2886, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2887, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2888, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2889, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2890, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2891, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2895, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2896, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2897, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2898, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2899, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2900, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2901, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2904, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2905, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2906, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2910, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2911, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2928, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2929, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2930, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2931, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2932, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2933, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2934, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2935, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2936, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2940, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2941, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2942, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2958, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2959, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2960, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2961, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2962, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2963, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2964, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2965, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2966, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2970, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2971, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2972, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2973, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2974, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2975, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2976, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2979, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2980, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2981, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2985, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2986, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3003, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3004, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3005, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3006, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3007, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3008, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3009, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3010, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3011, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3015, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3016, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3017, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3033, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3034, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3035, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3036, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3037, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3038, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3039, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3040, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3041, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3045, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3046, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3047, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3048, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3049, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3050, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3051, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3054, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3055, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3056, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3060, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3061, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3078, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3079, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3080, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3081, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3082, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3083, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3084, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3085, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3086, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3090, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3091, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3092, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3093, ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST) \ + _(3094, ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3095, ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3096, ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST) \ + _(3097, ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3098, ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3099, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3103, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3104, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3108, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3112, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3113, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3114, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3115, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3116, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3117, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3121, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3122, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3123, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3124, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3125, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3126, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3127, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3128, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3129, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3130, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3131, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3132, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3136, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3139, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3140, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3141, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3145, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3146, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3169, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3170, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3171, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3172, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3173, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3174, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3175, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3176, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3177, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3181, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3183, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3187, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3188, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3189, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3190, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3191, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3192, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3196, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3197, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3198, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3204, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3205, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3206, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3207, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3211, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3214, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3215, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3216, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3220, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3221, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3244, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3245, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3246, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3247, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3248, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3249, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3250, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3251, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3252, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3256, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3258, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3262, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3263, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3264, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3265, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3266, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3267, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3271, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3272, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3273, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3279, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3280, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3281, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3282, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3286, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3289, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3290, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3291, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3295, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3296, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3319, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3320, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3321, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3322, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3323, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3324, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3325, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3326, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3327, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3331, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3333, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3337, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3338, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3339, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3340, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3341, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3342, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3346, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3347, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3348, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3354, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3355, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3356, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3357, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3361, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3364, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3365, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3366, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3370, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3371, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3394, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3395, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3396, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3397, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3398, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3399, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3400, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3401, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3402, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3406, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3408, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3409, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3410, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3411, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3412, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ + _(3413, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3414, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3415, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3416, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ + _(3417, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3418, ZEND_POST_INC_LONG_SPEC_CV) \ + _(3419, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3420, ZEND_POST_DEC_LONG_SPEC_CV) \ + _(3421, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ _(3422, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3424, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3425, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ - _(3426, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3423, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3425, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3426, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ _(3427, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3429, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3430, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ - _(3431, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3428, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3430, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3431, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ _(3432, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3434, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3436, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3433, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3435, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ _(3437, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3439, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3440, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3441, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3438, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3440, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3441, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3442, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3444, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3445, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3446, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3443, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3445, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3446, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3447, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3449, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3455, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ - _(3456, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3448, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3450, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3456, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ _(3457, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3459, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3462, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ - _(3464, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ - _(3467, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ - _(3469, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ - _(3470, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ - _(3471, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ - _(3472, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ - _(3473, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ - _(3473+1, ZEND_NULL) + _(3458, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3460, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3463, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ + _(3465, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ + _(3468, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ + _(3470, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ + _(3471, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ + _(3472, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ + _(3473, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ + _(3474, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ + _(3474+1, ZEND_NULL) diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 0ece3e6f0c66..3a19bf20347b 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -21,7 +21,7 @@ #include #include -static const char *zend_vm_opcodes_names[212] = { +static const char *zend_vm_opcodes_names[213] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -234,9 +234,10 @@ static const char *zend_vm_opcodes_names[212] = { "ZEND_INIT_PARENT_PROPERTY_HOOK_CALL", "ZEND_DECLARE_ATTRIBUTED_CONST", "ZEND_TYPE_ASSERT", + "ZEND_FLUSH_DEFERRED_DTORS", }; -static uint32_t zend_vm_opcodes_flags[212] = { +static uint32_t zend_vm_opcodes_flags[213] = { 0x00000000, 0x00000b0b, 0x00000b0b, @@ -449,6 +450,7 @@ static uint32_t zend_vm_opcodes_flags[212] = { 0x01001103, 0x00000303, 0x01000003, + 0x00000000, }; ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 92b46e6628f3..cdb7502a087a 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -331,7 +331,8 @@ END_EXTERN_C() #define ZEND_INIT_PARENT_PROPERTY_HOOK_CALL 209 #define ZEND_DECLARE_ATTRIBUTED_CONST 210 #define ZEND_TYPE_ASSERT 211 +#define ZEND_FLUSH_DEFERRED_DTORS 212 -#define ZEND_VM_LAST_OPCODE 211 +#define ZEND_VM_LAST_OPCODE 212 #endif diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index ad0308f44e20..d14486f33879 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -94,6 +94,59 @@ static void zend_weakref_unref(zend_object *object, void *tagged_ptr) { } } +static void zend_weakref_detach_single( + void *ptr, uintptr_t tag, zend_object *object) +{ + if (tag == ZEND_WEAKREF_TAG_REF) { + zend_weakref *wr = ptr; + wr->referent = NULL; + } else { + HashTable *ht = ptr; + ZEND_ASSERT(tag == ZEND_WEAKREF_TAG_MAP || tag == ZEND_WEAKREF_TAG_BARE_HT); + if (ht->pDestructor == ZVAL_PTR_DTOR) { + zval *zv = zend_hash_index_find(ht, zend_object_to_weakref_key(object)); + if (zv) { + zend_dtor_buf *buf = &EG(deferred_dtors); + if (UNEXPECTED(buf->values_count == buf->values_capacity)) { + uint32_t capacity = buf->values_capacity ? buf->values_capacity + (buf->values_capacity >> 1) : 8; + buf->values = erealloc(buf->values, sizeof(zval) * capacity); + buf->values_capacity = capacity; + } + ZVAL_COPY_VALUE(&buf->values[buf->values_count++], zv); + ZVAL_UNDEF(zv); + } + } + zend_hash_index_del(ht, zend_object_to_weakref_key(object)); + } +} + +void zend_weakrefs_notify_detach(zend_object *object) +{ + const zend_ulong obj_key = zend_object_to_weakref_key(object); + void *tagged_ptr = zend_hash_index_find_ptr(&EG(weakrefs), obj_key); +#if ZEND_DEBUG + ZEND_ASSERT(tagged_ptr && "Tracking of the IS_OBJ_WEAKLY_REFERENCE flag should be precise"); +#endif + if (tagged_ptr) { + void *ptr = ZEND_WEAKREF_GET_PTR(tagged_ptr); + uintptr_t tag = ZEND_WEAKREF_GET_TAG(tagged_ptr); + if (tag == ZEND_WEAKREF_TAG_HT) { + HashTable *ht = ptr; + void *inner_ptr; + ZEND_HASH_MAP_FOREACH_PTR(ht, inner_ptr) { + zend_weakref_detach_single( + ZEND_WEAKREF_GET_PTR(inner_ptr), ZEND_WEAKREF_GET_TAG(inner_ptr), object); + } ZEND_HASH_FOREACH_END(); + zend_hash_destroy(ht); + FREE_HASHTABLE(ht); + } else { + zend_weakref_detach_single(ptr, tag, object); + } + zend_hash_index_del(&EG(weakrefs), obj_key); + } + GC_DEL_FLAGS(object, IS_OBJ_WEAKLY_REFERENCED); +} + static void zend_weakref_register(zend_object *object, void *payload) { GC_ADD_FLAGS(object, IS_OBJ_WEAKLY_REFERENCED); diff --git a/Zend/zend_weakrefs.h b/Zend/zend_weakrefs.h index 41662c33a300..028491f4f3d6 100644 --- a/Zend/zend_weakrefs.h +++ b/Zend/zend_weakrefs.h @@ -27,6 +27,7 @@ void zend_weakrefs_init(void); void zend_weakrefs_shutdown(void); ZEND_API void zend_weakrefs_notify(zend_object *object); +void zend_weakrefs_notify_detach(zend_object *object); ZEND_API zval *zend_weakrefs_hash_add(HashTable *ht, zend_object *key, zval *pData); ZEND_API zend_result zend_weakrefs_hash_del(HashTable *ht, zend_object *key); diff --git a/ext/bz2/tests/bzdecompress_input_too_large.phpt b/ext/bz2/tests/bzdecompress_input_too_large.phpt index 88c93d366c54..9774c6dbbfd6 100644 --- a/ext/bz2/tests/bzdecompress_input_too_large.phpt +++ b/ext/bz2/tests/bzdecompress_input_too_large.phpt @@ -10,6 +10,8 @@ if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test'); if (getenv('SKIP_SLOW_TESTS')) die('skip slow test'); if (PHP_INT_SIZE != 8) die('skip 64-bit only'); ?> +--CONFLICTS-- +all --FILE-- +--CONFLICTS-- +all --INI-- memory_limit=-1 --FILE-- diff --git a/ext/curl/tests/curl_multi_add_handle_lifecycle.phpt b/ext/curl/tests/curl_multi_add_handle_lifecycle.phpt index 3027f0c33152..5b5533885b88 100644 --- a/ext/curl/tests/curl_multi_add_handle_lifecycle.phpt +++ b/ext/curl/tests/curl_multi_add_handle_lifecycle.phpt @@ -44,6 +44,6 @@ echo "Removed", PHP_EOL; ?> --EXPECTF-- Removing +Removed MyClass::__destruct MyClass::__destruct -Removed diff --git a/ext/dom/tests/gh12616_3.phpt b/ext/dom/tests/gh12616_3.phpt index 158992075720..bf8c3d6b370d 100644 --- a/ext/dom/tests/gh12616_3.phpt +++ b/ext/dom/tests/gh12616_3.phpt @@ -45,7 +45,7 @@ foreach ($xpath->query("/container/child2/namespace::*") as $ns) { } ?> ---EXPECT-- +--EXPECTF-- @@ -81,7 +81,7 @@ object(DOMNameSpaceNode)#4 (10) { string(22) "(object value omitted)" } --- Namespaces of child1/foo (both nodes) --- -object(DOMNameSpaceNode)#5 (10) { +object(DOMNameSpaceNode)#8 (10) { ["nodeName"]=> string(9) "xmlns:xml" ["nodeValue"]=> @@ -103,7 +103,7 @@ object(DOMNameSpaceNode)#5 (10) { ["parentElement"]=> string(22) "(object value omitted)" } -object(DOMNameSpaceNode)#8 (10) { +object(DOMNameSpaceNode)#10 (10) { ["nodeName"]=> string(9) "xmlns:xml" ["nodeValue"]=> @@ -126,7 +126,7 @@ object(DOMNameSpaceNode)#8 (10) { string(22) "(object value omitted)" } --- Namespaces of child2 --- -object(DOMNameSpaceNode)#9 (10) { +object(DOMNameSpaceNode)#%d (10) { ["nodeName"]=> string(9) "xmlns:xml" ["nodeValue"]=> @@ -148,7 +148,7 @@ object(DOMNameSpaceNode)#9 (10) { ["parentElement"]=> string(22) "(object value omitted)" } -object(DOMNameSpaceNode)#5 (10) { +object(DOMNameSpaceNode)#%d (10) { ["nodeName"]=> string(7) "xmlns:x" ["nodeValue"]=> diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index fbbfab6b243c..1ca815f81225 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -1425,6 +1425,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op int call_level = 0; void *checkpoint = NULL; bool recv_emitted = false; /* emitted at least one RECV opcode */ + bool entry_flush_emitted = false; uint8_t smart_branch_opcode; uint32_t target_label, target_label2; uint32_t op1_info, op1_def_info, op2_info, res_info, res_use_info, op1_mem_info; @@ -1574,7 +1575,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op zend_jit_set_last_valid_opline(&ctx, op_array->opcodes + ssa->cfg.blocks[b].start); } if (ssa->cfg.blocks[b].flags & ZEND_BB_LOOP_HEADER) { - zend_jit_check_timeout(&ctx, op_array->opcodes + ssa->cfg.blocks[b].start, NULL); + zend_jit_check_loop_timeout(&ctx, op_array->opcodes + ssa->cfg.blocks[b].start); } if (!ssa->cfg.blocks[b].len) { zend_jit_bb_end(&ctx, b); @@ -1604,6 +1605,13 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op phi = phi->next; } } + if ((ssa->cfg.blocks[b].flags & ZEND_BB_TARGET) + && ssa->cfg.blocks[b].start != 0 + && !(ssa->cfg.blocks[b].flags & ZEND_BB_LOOP_HEADER)) { + if (!zend_jit_deferred_error_deopt(&ctx, op_array, ssa, b, op_array->opcodes + ssa->cfg.blocks[b].start, ssa->cfg.blocks[b].start)) { + goto jit_failure; + } + } end = ssa->cfg.blocks[b].start + ssa->cfg.blocks[b].len - 1; for (i = ssa->cfg.blocks[b].start; i <= end; i++) { zend_ssa_op *ssa_op = ssa->ops ? &ssa->ops[i] : NULL; @@ -1612,6 +1620,13 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op call_level++; } + if (!entry_flush_emitted) { + entry_flush_emitted = true; + if (!zend_jit_deferred_error_deopt(&ctx, op_array, ssa, b, opline, i)) { + goto jit_failure; + } + } + if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) { switch (opline->opcode) { case ZEND_PRE_INC: @@ -2529,6 +2544,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto done; case ZEND_FREE: case ZEND_FE_FREE: + if (opline->extended_value & ZEND_FREE_ON_RETURN) { + break; + } if (!zend_jit_free(&ctx, opline, OP1_INFO(), zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; @@ -2881,6 +2899,11 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } } + break; + case ZEND_FLUSH_DEFERRED_DTORS: + if (!zend_jit_flush_deferred_dtors(&ctx, opline)) { + goto jit_failure; + } break; default: if (!zend_jit_handler(&ctx, opline, @@ -2934,7 +2957,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } } if (!zend_jit_leave_func(&ctx, op_array, NULL, MAY_BE_ANY, left_frame, - NULL, NULL, (ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0, 1)) { + NULL, NULL, (ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0)) { goto jit_failure; } } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 64a48068f378..d5b65a1ce7a4 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -3437,6 +3437,54 @@ static void ZEND_FASTCALL zend_jit_exception_in_interrupt_handler_helper(void) } } +static void ZEND_FASTCALL zend_jit_flush_deferred_dtors_helper(zend_execute_data *execute_data) +{ + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } +} + +static void ZEND_FASTCALL zend_jit_flush_deferred_dtors_surface_helper(zend_execute_data *execute_data) +{ + zend_flush_deferred_dtors_surface(); + if (UNEXPECTED(EG(exception))) { + zend_rethrow_exception(execute_data); + } +} + +static void ZEND_FASTCALL zend_jit_check_deferred_errors(zend_execute_data *execute_data) +{ + bool pending_dtors = EG(deferred_dtors).count || EG(deferred_dtors).values_count; + + if ((EG(deferred_errors).size || pending_dtors) && execute_data->call) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } else { + if (pending_dtors) { + const zend_op *opline = EX(opline); + + if (opline >= EX(func)->op_array.opcodes + && opline <= EX(func)->op_array.opcodes + EX(func)->op_array.num_args) { + zend_flush_deferred_dtors(); + } else { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } + } + zend_flush_deferred_errors(); + } +} + +static void ZEND_FASTCALL zend_jit_check_deferred_loop(zend_execute_data *execute_data) +{ + if ((EG(deferred_errors).size || EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && execute_data->call) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } else { + zend_flush_deferred_dtors(); + zend_flush_deferred_errors(); + } +} + static zend_string* ZEND_FASTCALL zend_jit_rope_end(zend_string **rope, uint32_t count) { zend_string *ret; diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 7b5f93f70db7..4b05bd072688 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -335,6 +335,7 @@ typedef enum _zend_jit_trace_stop { #define ZEND_JIT_EXIT_METHOD_CALL (1<<9) /* exit because of polymorphic INIT_METHOD_CALL call */ #define ZEND_JIT_EXIT_INVALIDATE (1<<10) /* invalidate current trace */ #define ZEND_JIT_EXIT_CHECK_EXCEPTION (1<<11) +#define ZEND_JIT_EXIT_LOOP_INTERRUPT (1<<12) #define ZEND_JIT_EXIT_FIXED (1U<<31) /* the exit_info can't be changed by zend_jit_snapshot_handler() */ diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index b0b04456706b..5d4d23c50c3e 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -242,6 +242,7 @@ static size_t tsrm_tls_offset = -1; _(exception_handler_free_op2, IR_SKIP_PROLOGUE) \ _(exception_handler_free_op1_op2, IR_SKIP_PROLOGUE) \ _(interrupt_handler, IR_SKIP_PROLOGUE) \ + _(loop_interrupt_handler, IR_SKIP_PROLOGUE) \ _(leave_function_handler, IR_SKIP_PROLOGUE) \ _(negative_shift, IR_SKIP_PROLOGUE) \ _(mod_by_zero, IR_SKIP_PROLOGUE) \ @@ -649,6 +650,7 @@ static void jit_SNAPSHOT(zend_jit_ctx *jit, ir_ref addr) || ptr == zend_jit_stub_handlers[jit_stub_exception_handler_free_op1_op2] || ptr == zend_jit_stub_handlers[jit_stub_exception_handler_free_op2] || ptr == zend_jit_stub_handlers[jit_stub_interrupt_handler] + || ptr == zend_jit_stub_handlers[jit_stub_loop_interrupt_handler] || ptr == zend_jit_stub_handlers[jit_stub_leave_function_handler] || ptr == zend_jit_stub_handlers[jit_stub_negative_shift] || ptr == zend_jit_stub_handlers[jit_stub_mod_by_zero] @@ -1944,6 +1946,32 @@ static void zend_jit_check_timeout(zend_jit_ctx *jit, const zend_op *opline, con } } +static void zend_jit_check_loop_timeout(zend_jit_ctx *jit, const zend_op *opline) +{ + ir_ref if_interrupt, if_timeout, if_deferred, ride_path, cont_path; + + if_interrupt = ir_IF(ir_LOAD_U8(jit_EG(vm_interrupt))); + ir_IF_TRUE_cold(if_interrupt); + + if_timeout = ir_IF(ir_LOAD_U8(jit_EG(timed_out))); + ir_IF_TRUE(if_timeout); + jit_LOAD_IP_ADDR(jit, opline); + ir_IJMP(jit_STUB_ADDR(jit, jit_stub_loop_interrupt_handler)); + ir_IF_FALSE(if_timeout); + + if_deferred = ir_IF(ir_LOAD_U32(jit_EG(deferred_errors.size))); + ir_IF_FALSE(if_deferred); + jit_LOAD_IP_ADDR(jit, opline); + ir_IJMP(jit_STUB_ADDR(jit, jit_stub_loop_interrupt_handler)); + ir_IF_TRUE(if_deferred); + ride_path = ir_END(); + + ir_IF_FALSE(if_interrupt); + cont_path = ir_END(); + + ir_MERGE_2(ride_path, cont_path); +} + static void zend_jit_vm_enter(zend_jit_ctx *jit, ir_ref to_opline) { // ZEND_VM_ENTER() @@ -2060,7 +2088,7 @@ static int zend_jit_exception_handler_free_op2_stub(zend_jit_ctx *jit) return 1; } -static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) +static int zend_jit_interrupt_handler_stub_ex(zend_jit_ctx *jit, bool loop_interrupt) { ir_ref if_timeout, if_exception; @@ -2073,16 +2101,21 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) ir_CALL(IR_VOID, ir_CONST_FUNC(zend_timeout)); ir_MERGE_WITH_EMPTY_TRUE(if_timeout); + if (loop_interrupt) { + ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_check_deferred_loop), jit_FP(jit)); + } else { + ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_check_deferred_errors), jit_FP(jit)); + } if (zend_interrupt_function) { ir_CALL_1(IR_VOID, ir_CONST_FUNC(zend_interrupt_function), jit_FP(jit)); - if_exception = ir_IF(ir_LOAD_A(jit_EG(exception))); - ir_IF_TRUE(if_exception); - ir_CALL(IR_VOID, ir_CONST_FUNC(zend_jit_exception_in_interrupt_handler_helper)); - ir_MERGE_WITH_EMPTY_FALSE(if_exception); - - jit_STORE_FP(jit, ir_LOAD_A(jit_EG(current_execute_data))); - jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); } + if_exception = ir_IF(ir_LOAD_A(jit_EG(exception))); + ir_IF_TRUE(if_exception); + ir_CALL(IR_VOID, ir_CONST_FUNC(zend_jit_exception_in_interrupt_handler_helper)); + ir_MERGE_WITH_EMPTY_FALSE(if_exception); + + jit_STORE_FP(jit, ir_LOAD_A(jit_EG(current_execute_data))); + jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { zend_jit_tailcall_handler(jit, ir_LOAD_A(jit_IP(jit))); @@ -2092,6 +2125,16 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) return 1; } +static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) +{ + return zend_jit_interrupt_handler_stub_ex(jit, false); +} + +static int zend_jit_loop_interrupt_handler_stub(zend_jit_ctx *jit) +{ + return zend_jit_interrupt_handler_stub_ex(jit, true); +} + static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit) { #if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL @@ -2496,7 +2539,7 @@ static int zend_jit_trace_escape_stub(zend_jit_ctx *jit) static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) { - ir_ref ref, ret, if_zero, addr; + ir_ref ref, ret, if_zero, if_loop_interrupt, addr; // EX(opline) = opline ir_STORE(jit_EX(opline), jit_IP(jit)); @@ -2521,15 +2564,22 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) ir_IF_FALSE(if_zero); ir_GUARD(ir_GE(ret, ir_CONST_I32(0)), jit_STUB_ADDR(jit, jit_stub_trace_halt)); + if_loop_interrupt = ir_IF(ir_EQ(ret, ir_CONST_I32(ZEND_JIT_EXIT_LOOP_INTERRUPT))); + ir_IF_TRUE(if_loop_interrupt); ref = jit_EG(current_execute_data); jit_STORE_FP(jit, ir_LOAD_A(ref)); - ref = ir_LOAD_A(jit_EX(opline)); jit_STORE_IP(jit, ref); + ir_IJMP(jit_STUB_ADDR(jit, jit_stub_loop_interrupt_handler)); - // check for interrupt (try to avoid this ???) - zend_jit_check_timeout(jit, NULL, NULL); + ir_IF_FALSE(if_loop_interrupt); + + ref = jit_EG(current_execute_data); + jit_STORE_FP(jit, ir_LOAD_A(ref)); + + ref = ir_LOAD_A(jit_EX(opline)); + jit_STORE_IP(jit, ref); addr = zend_jit_orig_opline_handler(jit); if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { @@ -3132,6 +3182,10 @@ static void zend_jit_setup_disasm(void) REGISTER_HELPER(zend_free_extra_named_params); REGISTER_HELPER(zend_jit_free_call_frame); REGISTER_HELPER(zend_jit_exception_in_interrupt_handler_helper); + REGISTER_HELPER(zend_jit_check_deferred_errors); + REGISTER_HELPER(zend_jit_check_deferred_loop); + REGISTER_HELPER(zend_jit_flush_deferred_dtors_helper); + REGISTER_HELPER(zend_jit_flush_deferred_dtors_surface_helper); REGISTER_HELPER(zend_jit_verify_arg_slow); REGISTER_HELPER(zend_missing_arg_error); REGISTER_HELPER(zend_jit_only_vars_by_reference); @@ -4177,6 +4231,26 @@ static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_th return 1; } +static int zend_jit_flush_deferred_dtors(zend_jit_ctx *jit, const zend_op *opline) +{ + ir_ref if_pending = ir_IF(ir_OR_U32( + ir_LOAD_U32(jit_EG(deferred_dtors.count)), + ir_LOAD_U32(jit_EG(deferred_dtors.values_count)))); + + ir_IF_TRUE_cold(if_pending); + jit_SET_EX_OPLINE(jit, opline); + if ((opline + 1)->opcode == ZEND_THROW) { + ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_flush_deferred_dtors_surface_helper), jit_FP(jit)); + } else { + ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_flush_deferred_dtors_helper), jit_FP(jit)); + } + zend_jit_check_exception(jit); + ir_ref cold_path = ir_END(); + ir_IF_FALSE(if_pending); + ir_MERGE_WITH(cold_path); + return 1; +} + static int zend_jit_tail_handler(zend_jit_ctx *jit, const zend_op *opline) { ir_ref ref; @@ -4339,6 +4413,68 @@ static int zend_jit_store_var(zend_jit_ctx *jit, uint32_t info, int var, int ssa return zend_jit_spill_store(jit, src, dst, info, set_type); } +static bool zend_jit_ssa_var_live_at(const zend_ssa *ssa, int v, uint32_t i) +{ + int use = ssa->vars[v].use_chain; + + while (use >= 0) { + if ((uint32_t)use >= i) { + return 1; + } + use = zend_ssa_next_use(ssa->ops, v, use); + } + return 0; +} + +static int zend_jit_materialize_live_vars(zend_jit_ctx *jit, const zend_op_array *op_array, zend_ssa *ssa, int b, uint32_t i) +{ + int v; + zend_ssa_phi *phi; + + if (!jit->ra) { + return 1; + } + phi = ssa->blocks[b].phis; + while (phi) { + v = phi->ssa_var; + if (phi->pi < 0 + && jit->ra[v].ref + && !(jit->ra[v].flags & ZREG_LOAD)) { + if (!zend_jit_store_var(jit, ssa->var_info[v].type, ssa->vars[v].var, v, 1)) { + return 0; + } + } + phi = phi->next; + } + for (v = 0; v < ssa->vars_count; v++) { + if (jit->ra[v].ref + && !(jit->ra[v].flags & ZREG_LOAD) + && ssa->vars[v].definition >= 0 + && (uint32_t)ssa->vars[v].definition < i + && zend_jit_ssa_var_live_at(ssa, v, i)) { + if (!zend_jit_store_var(jit, ssa->var_info[v].type, ssa->vars[v].var, v, 1)) { + return 0; + } + } + } + return 1; +} + +static int zend_jit_deferred_error_deopt(zend_jit_ctx *jit, const zend_op_array *op_array, zend_ssa *ssa, int b, const zend_op *opline, uint32_t i) +{ + ir_ref if_deferred = ir_IF(ir_LOAD_U32(jit_EG(deferred_errors.size))); + + ir_IF_TRUE_cold(if_deferred); + if (!zend_jit_materialize_live_vars(jit, op_array, ssa, b, i)) { + return 0; + } + ir_STORE(jit_EG(current_execute_data), jit_FP(jit)); + jit_LOAD_IP_ADDR(jit, opline); + ir_IJMP(jit_STUB_ADDR(jit, jit_stub_interrupt_handler)); + ir_IF_FALSE(if_deferred); + return 1; +} + static int zend_jit_store_ref(zend_jit_ctx *jit, uint32_t info, int var, int32_t src, bool set_type) { zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, EX_NUM_TO_VAR(var)); @@ -10463,6 +10599,8 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen } else { zend_basic_block *bb; + zend_jit_check_timeout(jit, NULL, NULL); + do { if (recursive_call_through_jmp) { ir_ref begin, end; @@ -10538,14 +10676,6 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen // JIT: EG(current_execute_data) = execute_data; ir_STORE(jit_EG(current_execute_data), rx); - bool may_have_observer = ZEND_OBSERVER_ENABLED && (!func || (func->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) == 0); - if (may_have_observer) { - ir_ref observer_handler; - struct jit_observer_fcall_is_unobserved_data unobserved_data = jit_observer_fcall_is_unobserved_start(jit, func, &observer_handler, rx, func_ref ? func_ref : ir_LOAD_A(jit_CALL(rx, func))); - jit_observer_fcall_begin(jit, rx, observer_handler); - jit_observer_fcall_is_unobserved_end(jit, &unobserved_data); - } - // JIT: ZVAL_NULL(EX_VAR(opline->result.var)); ir_ref res_addr = IR_UNUSED, func_ptr; @@ -10570,6 +10700,38 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); + ir_ref skip_path = IR_UNUSED; + + if (!RETURN_VALUE_USED(opline)) { + ir_ref flush_inputs = IR_UNUSED; + ir_ref if_pending = ir_IF(ir_OR_U32( + ir_LOAD_U32(jit_EG(deferred_dtors.count)), + ir_LOAD_U32(jit_EG(deferred_dtors.values_count)))); + + ir_IF_TRUE_cold(if_pending); + ir_ref if_nested = ir_IF(ir_LOAD_A(jit_EX(call))); + ir_IF_FALSE(if_nested); + ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_flush_deferred_dtors_surface)); + ir_ref if_exception = ir_IF(ir_LOAD_A(jit_EG_exception(jit))); + ir_IF_TRUE_cold(if_exception); + skip_path = ir_END(); + ir_IF_FALSE(if_exception); + ir_END_list(flush_inputs); + ir_IF_TRUE(if_nested); + ir_END_list(flush_inputs); + ir_IF_FALSE(if_pending); + ir_END_list(flush_inputs); + ir_MERGE_list(flush_inputs); + } + + bool may_have_observer = ZEND_OBSERVER_ENABLED && (!func || (func->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) == 0); + if (may_have_observer) { + ir_ref observer_handler; + struct jit_observer_fcall_is_unobserved_data unobserved_data = jit_observer_fcall_is_unobserved_start(jit, func, &observer_handler, rx, func_ref ? func_ref : ir_LOAD_A(jit_CALL(rx, func))); + jit_observer_fcall_begin(jit, rx, observer_handler); + jit_observer_fcall_is_unobserved_end(jit, &unobserved_data); + } + zend_jit_reset_last_valid_opline(jit); // JIT: (zend_execute_internal ? zend_execute_internal : fbc->internal_function.handler)(call, ret); @@ -10592,12 +10754,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen jit_observer_fcall_end(jit, rx, res_ref); } - /* When zend_interrupt_function is set, it gets called while - * the frame is still on top. This is less efficient than - * doing it later once it's popped off. There is code further - * down that handles when there isn't an interrupt function. - */ - if (zend_interrupt_function) { + { // JIT: if (EG(vm_interrupt)) zend_fcall_interrupt(execute_data); ir_ref if_interrupt = ir_IF(ir_LOAD_U8(jit_EG(vm_interrupt))); ir_IF_TRUE_cold(if_interrupt); @@ -10605,6 +10762,10 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen ir_MERGE_WITH_EMPTY_FALSE(if_interrupt); } + if (skip_path) { + ir_MERGE_WITH(skip_path); + } + // JIT: EG(current_execute_data) = execute_data; ir_STORE(jit_EG(current_execute_data), jit_FP(jit)); @@ -10715,25 +10876,6 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen ir_GUARD_NOT(ir_LOAD_A(jit_EG_exception(jit)), jit_STUB_ADDR(jit, jit_stub_icall_throw)); - /* If there isn't a zend_interrupt_function, the timeout is - * handled here because it's more efficient. - */ - if (!zend_interrupt_function) { - // TODO: Can we avoid checking for interrupts after each call ??? - if (trace && jit->last_valid_opline != opline) { - int32_t exit_point = zend_jit_trace_get_exit_point(opline + 1, ZEND_JIT_EXIT_TO_VM); - - exit_addr = zend_jit_trace_get_exit_addr(exit_point); - if (!exit_addr) { - return 0; - } - } else { - exit_addr = NULL; - } - - zend_jit_check_timeout(jit, opline + 1, exit_addr); - } - if ((!trace || !func) && opline->opcode != ZEND_DO_ICALL) { jit_LOAD_IP_ADDR(jit, opline + 1); } else if (trace @@ -11061,8 +11203,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, bool left_frame, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info, - int indirect_var_access, - int may_throw) + int indirect_var_access) { bool may_be_top_frame = JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || @@ -11086,6 +11227,17 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, !TRACE_FRAME_NO_NEED_RELEASE_THIS(JIT_G(current_frame))); ir_ref call_info = IR_UNUSED, ref, cold_path = IR_UNUSED; + { + ir_ref if_deferred = ir_IF(ir_LOAD_U32(jit_EG(deferred_errors.size))); + ir_IF_TRUE_cold(if_deferred); + ir_ref saved_ced = ir_LOAD_A(jit_EG(current_execute_data)); + ir_STORE(jit_EX(opline), jit_IP(jit)); + ir_STORE(jit_EG(current_execute_data), jit_FP(jit)); + ir_CALL(IR_VOID, ir_CONST_FUNC(zend_flush_deferred_errors)); + ir_STORE(jit_EG(current_execute_data), saved_ced); + ir_MERGE_WITH_EMPTY_FALSE(if_deferred); + } + if (may_need_call_helper) { if (!left_frame) { left_frame = true; @@ -11167,8 +11319,6 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, if (fast_path) { ir_MERGE_WITH(fast_path); } - // TODO: avoid EG(excption) check for $this->foo() calls - may_throw = 1; } // JIT: EG(vm_stack_top) = (zval*)execute_data @@ -11203,6 +11353,39 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, #endif } + { + ir_ref flush_inputs = IR_UNUSED; + ir_ref if_pending = ir_IF(ir_OR_U32( + ir_LOAD_U32(jit_EG(deferred_dtors.count)), + ir_LOAD_U32(jit_EG(deferred_dtors.values_count)))); + + ir_IF_TRUE_cold(if_pending); + ir_ref if_call = ir_IF(ir_LOAD_A(jit_EX(call))); + ir_IF_FALSE(if_call); + if (trace->op != ZEND_JIT_TRACE_END + && (JIT_G(current_frame) && !TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame)))) { + const zend_jit_trace_rec *q = trace; + + ZEND_ASSERT(q->op == ZEND_JIT_TRACE_BACK); + do { + q++; + } while (q->op == ZEND_JIT_TRACE_INIT_CALL); + ZEND_ASSERT(q->op == ZEND_JIT_TRACE_VM || q->op == ZEND_JIT_TRACE_END); + ZEND_ASSERT(q->opline != NULL); + ir_STORE(jit_EX(opline), ir_CONST_ADDR(q->opline)); + } else { + ir_STORE(jit_EX(opline), jit_IP(jit)); + } + ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_flush_deferred_dtors)); + ir_GUARD_NOT(ir_LOAD_A(jit_EG(exception)), jit_STUB_ADDR(jit, jit_stub_leave_throw)); + ir_END_list(flush_inputs); + ir_IF_TRUE(if_call); + ir_END_list(flush_inputs); + ir_IF_FALSE(if_pending); + ir_END_list(flush_inputs); + ir_MERGE_list(flush_inputs); + } + if (cold_path) { ir_MERGE_WITH(cold_path); } @@ -11211,13 +11394,8 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, && (!JIT_G(current_frame) || TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame)))) { const zend_op *next_opline = trace->opline; - if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) - && (op1_info & MAY_BE_RC1) - && (op1_info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY))) { - /* exception might be thrown during destruction of unused return value */ - // JIT: if (EG(exception)) - ir_GUARD_NOT(ir_LOAD_A(jit_EG(exception)), jit_STUB_ADDR(jit, jit_stub_leave_throw)); - } + // JIT: if (EG(exception)) + ir_GUARD_NOT(ir_LOAD_A(jit_EG(exception)), jit_STUB_ADDR(jit, jit_stub_leave_throw)); do { trace++; } while (trace->op == ZEND_JIT_TRACE_INIT_CALL); @@ -11249,17 +11427,30 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, zend_jit_set_last_valid_opline(jit, trace->opline); return 1; - } else if (may_throw || - (((opline->op1_type & (IS_VAR|IS_TMP_VAR)) - && (op1_info & MAY_BE_RC1) - && (op1_info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY))) - && (!JIT_G(current_frame) || TRACE_FRAME_IS_RETURN_VALUE_UNUSED(JIT_G(current_frame))))) { + } else { // JIT: if (EG(exception)) ir_GUARD_NOT(ir_LOAD_A(jit_EG(exception)), jit_STUB_ADDR(jit, jit_stub_leave_throw)); } return 1; } else { + ir_ref flush_inputs = IR_UNUSED; + ir_ref if_pending = ir_IF(ir_OR_U32( + ir_LOAD_U32(jit_EG(deferred_dtors.count)), + ir_LOAD_U32(jit_EG(deferred_dtors.values_count)))); + + ir_IF_TRUE_cold(if_pending); + ir_ref if_call = ir_IF(ir_LOAD_A(jit_EX(call))); + ir_IF_FALSE(if_call); + ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_flush_deferred_dtors)); + ir_GUARD_NOT(ir_LOAD_A(jit_EG(exception)), jit_STUB_ADDR(jit, jit_stub_leave_throw)); + ir_END_list(flush_inputs); + ir_IF_TRUE(if_call); + ir_END_list(flush_inputs); + ir_IF_FALSE(if_pending); + ir_END_list(flush_inputs); + ir_MERGE_list(flush_inputs); + // JIT: if (EG(exception)) ir_GUARD_NOT(ir_LOAD_A(jit_EG(exception)), jit_STUB_ADDR(jit, jit_stub_leave_throw)); // JIT: opline = EX(opline) + 1 diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 77bfaa03473a..0a8133eff907 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -5596,7 +5596,6 @@ static zend_vm_opcode_handler_t zend_jit_trace(zend_jit_trace_rec *trace_buffer, } } else { int j; - int may_throw = 0; bool left_frame = 0; if (!zend_jit_return(&ctx, opline, op_array, @@ -5638,17 +5637,12 @@ static zend_vm_opcode_handler_t zend_jit_trace(zend_jit_trace_rec *trace_buffer, if (!zend_jit_free_cv(&ctx, info, j)) { goto jit_failure; } - if (info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_RESOURCE)) { - if (info & MAY_BE_RC1) { - may_throw = 1; - } - } } } } if (!zend_jit_leave_func(&ctx, op_array, opline, op1_info, left_frame, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM], - (op_array_ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0, may_throw)) { + (op_array_ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0)) { goto jit_failure; } } @@ -6208,6 +6202,9 @@ static zend_vm_opcode_handler_t zend_jit_trace(zend_jit_trace_rec *trace_buffer, goto done; case ZEND_FREE: case ZEND_FE_FREE: + if (opline->extended_value & ZEND_FREE_ON_RETURN) { + break; + } op1_info = OP1_INFO(); if (!zend_jit_free(&ctx, opline, op1_info, zend_may_throw(opline, ssa_op, op_array, ssa))) { @@ -6473,6 +6470,11 @@ static zend_vm_opcode_handler_t zend_jit_trace(zend_jit_trace_rec *trace_buffer, goto jit_failure; } goto done; + case ZEND_FLUSH_DEFERRED_DTORS: + if (!zend_jit_flush_deferred_dtors(&ctx, opline)) { + goto jit_failure; + } + goto done; case ZEND_FRAMELESS_ICALL_0: jit_frameless_icall0(jit, opline); goto done; @@ -7237,14 +7239,15 @@ static zend_vm_opcode_handler_t zend_jit_trace(zend_jit_trace_rec *trace_buffer, || (ra && zend_jit_trace_stack_needs_deoptimization(stack, op_array->last_var + op_array->T))) { /* Deoptimize to the first instruction of the loop */ - uint32_t exit_point = zend_jit_trace_get_exit_point(trace_buffer[1].opline, ZEND_JIT_EXIT_TO_VM); + uint32_t exit_point = zend_jit_trace_get_exit_point( + trace_buffer[1].opline, ZEND_JIT_EXIT_TO_VM | ZEND_JIT_EXIT_LOOP_INTERRUPT); timeout_exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!timeout_exit_addr) { goto jit_failure; } } else { - timeout_exit_addr = zend_jit_stub_handlers[jit_stub_interrupt_handler]; + timeout_exit_addr = zend_jit_stub_handlers[jit_stub_loop_interrupt_handler]; } } @@ -7308,13 +7311,15 @@ static zend_vm_opcode_handler_t zend_jit_trace(zend_jit_trace_rec *trace_buffer, for (i = 0; i < op_array->last_var + op_array->T; i++) { SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1); } - exit_point = zend_jit_trace_get_exit_point(zend_jit_traces[t->link].opline, ZEND_JIT_EXIT_TO_VM); + exit_point = zend_jit_trace_get_exit_point( + zend_jit_traces[t->link].opline, + ZEND_JIT_EXIT_TO_VM | ZEND_JIT_EXIT_LOOP_INTERRUPT); timeout_exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!timeout_exit_addr) { goto jit_failure; } } else { - timeout_exit_addr = zend_jit_stub_handlers[jit_stub_interrupt_handler]; + timeout_exit_addr = zend_jit_stub_handlers[jit_stub_loop_interrupt_handler]; } } zend_jit_trace_link_to_root(&ctx, &zend_jit_traces[t->link], timeout_exit_addr); @@ -8822,6 +8827,10 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf EX(opline) = opline; } + if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_LOOP_INTERRUPT) { + return ZEND_JIT_EXIT_LOOP_INTERRUPT; + } + if (zend_atomic_bool_load_ex(&EG(vm_interrupt)) || JIT_G(tracing)) { return 1; /* Lock-free check if the side trace was already JIT-ed or blacklist-ed in another process */ diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 85a81c1573bc..61f4875d50c7 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -102,6 +102,13 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPC { zend_execute_data *old_execute_data; + if (UNEXPECTED(EG(deferred_errors).size || EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + EX(opline) = opline; + zend_flush_deferred_dtors(); + zend_flush_deferred_errors(); + } + + EG(frame_teardown)++; if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_clean_and_cache_symbol_table(EX(symbol_table)); } @@ -115,6 +122,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPC if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { zend_free_extra_named_params(EX(extra_named_params)); } + EG(frame_teardown)--; old_execute_data = execute_data; execute_data = EX(prev_execute_data); @@ -1094,6 +1102,21 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, #endif if (UNEXPECTED(execute_data != prev_execute_data)) { + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count) + && !EX(call) + && opline->opcode != ZEND_DO_FCALL + && opline->opcode != ZEND_DO_ICALL + && opline->opcode != ZEND_DO_UCALL + && opline->opcode != ZEND_DO_FCALL_BY_NAME) { + EX(opline) = opline; + zend_flush_deferred_dtors(); + if (UNEXPECTED(EG(exception))) { + opline = EX(opline); + stop = ZEND_JIT_TRACE_STOP_EXCEPTION; + break; + } + } + op_array = &EX(func)->op_array; jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array); @@ -1114,6 +1137,18 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, if (execute_data->prev_execute_data == prev_execute_data) { /* Enter into function */ + if (UNEXPECTED(EG(deferred_dtors).count || EG(deferred_dtors).values_count)) { + stop = ZEND_JIT_TRACE_STOP_INTERPRETER; + break; + } + if (UNEXPECTED(EG(deferred_errors).size)) { + EX(opline) = opline; + zend_flush_deferred_errors(); + if (UNEXPECTED(EG(exception))) { + stop = ZEND_JIT_TRACE_STOP_EXCEPTION; + break; + } + } prev_call = NULL; if (level > ZEND_JIT_TRACE_MAX_CALL_DEPTH) { stop = ZEND_JIT_TRACE_STOP_TOO_DEEP; diff --git a/ext/opcache/tests/jit/assign_043.phpt b/ext/opcache/tests/jit/assign_043.phpt index edb0cb212ab0..6c86b94e545f 100644 --- a/ext/opcache/tests/jit/assign_043.phpt +++ b/ext/opcache/tests/jit/assign_043.phpt @@ -17,5 +17,5 @@ try { echo $e->getMessage(), "\n"; } ?> ---EXPECT-- -Undefined variable $b +--EXPECTF-- +Undefined variable $b \ No newline at end of file diff --git a/ext/opcache/tests/jit/assign_dim_005.phpt b/ext/opcache/tests/jit/assign_dim_005.phpt index e7bfdabacc4f..b839739574bb 100644 --- a/ext/opcache/tests/jit/assign_dim_005.phpt +++ b/ext/opcache/tests/jit/assign_dim_005.phpt @@ -16,6 +16,11 @@ $a[$c] = 'x' ; var_dump($a); ?> --EXPECT-- +array(1) { + [""]=> + string(1) "x" +} Error: Undefined variable $c +Error: Using null as an array offset is deprecated, use an empty string instead Error: Undefined variable $c -NULL +Error: Using null as an array offset is deprecated, use an empty string instead diff --git a/ext/opcache/tests/jit/assign_dim_007.phpt b/ext/opcache/tests/jit/assign_dim_007.phpt index 0df4e291ae93..590ab14b6670 100644 --- a/ext/opcache/tests/jit/assign_dim_007.phpt +++ b/ext/opcache/tests/jit/assign_dim_007.phpt @@ -18,7 +18,9 @@ x($y); var_dump($x,$y); ?> --EXPECT-- -array(0) { +array(1) { + [0]=> + int(1) } array(1) { [0]=> diff --git a/ext/opcache/tests/jit/assign_dim_011.phpt b/ext/opcache/tests/jit/assign_dim_011.phpt index 5df415c89e6c..daad27634196 100644 --- a/ext/opcache/tests/jit/assign_dim_011.phpt +++ b/ext/opcache/tests/jit/assign_dim_011.phpt @@ -18,7 +18,11 @@ try { } ?> DONE ---EXPECT-- +--EXPECTF-- Err: Automatic conversion of false to array is deprecated -Exception: Cannot use a scalar value as an array -DONE + +Fatal error: Uncaught Error: Cannot use a scalar value as an array in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(8192, 'Automatic conve...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/ext/opcache/tests/jit/assign_dim_014.phpt b/ext/opcache/tests/jit/assign_dim_014.phpt index 574b05258421..45958d82edab 100644 --- a/ext/opcache/tests/jit/assign_dim_014.phpt +++ b/ext/opcache/tests/jit/assign_dim_014.phpt @@ -14,5 +14,6 @@ $a[$y] = function(){}; ?> DONE --EXPECT-- -Error: Undefined variable $y DONE +Error: Undefined variable $y +Error: Using null as an array offset is deprecated, use an empty string instead diff --git a/ext/opcache/tests/jit/assign_dim_015.phpt b/ext/opcache/tests/jit/assign_dim_015.phpt index 2a5b6d46d37a..3cfb75a31b74 100644 --- a/ext/opcache/tests/jit/assign_dim_015.phpt +++ b/ext/opcache/tests/jit/assign_dim_015.phpt @@ -14,5 +14,5 @@ $my_var[] = $y; ?> DONE --EXPECT-- -Error: Undefined variable $y DONE +Error: Undefined variable $y diff --git a/ext/opcache/tests/jit/assign_dim_op_006.phpt b/ext/opcache/tests/jit/assign_dim_op_006.phpt index 8bfb9197177a..b2b606245be8 100644 --- a/ext/opcache/tests/jit/assign_dim_op_006.phpt +++ b/ext/opcache/tests/jit/assign_dim_op_006.phpt @@ -15,4 +15,7 @@ $my_var[000000000000000000000100000000000000000000000000000000000000000000000000 var_dump($my_var); ?> --EXPECT-- -int(0) +array(1) { + [0]=> + string(3) "xyz" +} diff --git a/ext/opcache/tests/jit/count_001.phpt b/ext/opcache/tests/jit/count_001.phpt index 2fb1c52d2855..123413e209aa 100644 --- a/ext/opcache/tests/jit/count_001.phpt +++ b/ext/opcache/tests/jit/count_001.phpt @@ -61,8 +61,13 @@ for ($i = 0; $i < 5; $i++) { 3 4 5 +Unreachable Caught In destructor +Unreachable Caught In destructor +Unreachable Caught In destructor +Unreachable Caught In destructor +Unreachable Caught In destructor \ No newline at end of file diff --git a/ext/opcache/tests/jit/fetch_dim_rw_004.phpt b/ext/opcache/tests/jit/fetch_dim_rw_004.phpt index ae639c8f56ba..b0f18f9746c5 100644 --- a/ext/opcache/tests/jit/fetch_dim_rw_004.phpt +++ b/ext/opcache/tests/jit/fetch_dim_rw_004.phpt @@ -12,12 +12,12 @@ $k=[]; $y[$k]++; ?> --EXPECTF-- -Fatal error: Uncaught TypeError: {closure:%s:%d}(): Argument #1 ($y) must be of type y, int given, called in %s on line %d and defined in %s:%d +Fatal error: Uncaught TypeError: Cannot access offset of type array on array in %s:%d Stack trace: -#0 %s(%d): {closure:%s:%d}(2, 'Undefined varia...', '%s', 5) -#1 {main} +#0 {main} -Next TypeError: Cannot access offset of type array on array in %sfetch_dim_rw_004.php:5 +Next TypeError: {closure:%s:%d}(): Argument #1 ($y) must be of type y, int given, called in %s on line %d and defined in %s:%d Stack trace: -#0 {main} - thrown in %sfetch_dim_rw_004.php on line 5 +#0 %s(%d): {closure:%s:%d}(2, 'Undefined varia...', '%s', 5) +#1 {main} + thrown in %s on line %d \ No newline at end of file diff --git a/ext/opcache/tests/jit/gh18262-002.phpt b/ext/opcache/tests/jit/gh18262-002.phpt index b82723abaa29..c4de9ff0375a 100644 --- a/ext/opcache/tests/jit/gh18262-002.phpt +++ b/ext/opcache/tests/jit/gh18262-002.phpt @@ -26,9 +26,11 @@ foreach ($tests as $obj) { ?> --EXPECTF-- int(1) +NULL Fatal error: Uncaught Exception: Undefined property: B::$b in %s:%d Stack trace: -#0 %s(%d): {closure:%s:%d}(2, 'Undefined prope...', '%s', %d) -#1 {main} +#0 [internal function]: {closure:%s:%d}(2, 'Undefined prope...', '%s', %d) +#1 %s(%d): var_dump(NULL) +#2 {main} thrown in %s on line %d diff --git a/ext/opcache/tests/jit/gh18262-003.phpt b/ext/opcache/tests/jit/gh18262-003.phpt index a3c3e037632f..9f3f8c57ad55 100644 --- a/ext/opcache/tests/jit/gh18262-003.phpt +++ b/ext/opcache/tests/jit/gh18262-003.phpt @@ -32,4 +32,5 @@ foreach ($tests as $obj) { --EXPECT-- int(1) string(3) "str" +NULL Exception: Undefined property: B::$b diff --git a/ext/opcache/tests/jit/gh18262-004.phpt b/ext/opcache/tests/jit/gh18262-004.phpt index c8dccd30c98a..3cdc8ad7fe39 100644 --- a/ext/opcache/tests/jit/gh18262-004.phpt +++ b/ext/opcache/tests/jit/gh18262-004.phpt @@ -31,6 +31,7 @@ int(1) Fatal error: Uncaught Exception: B::__destruct in %s:%d Stack trace: -#0 %s(%d): B->__destruct() -#1 {main} +#0 [internal function]: B->__destruct() +#1 %s(%d): var_dump('str') +#2 {main} thrown in %s on line %d diff --git a/ext/opcache/tests/jit/qm_assign_undef_exception.phpt b/ext/opcache/tests/jit/qm_assign_undef_exception.phpt index 4e93e2ed7e56..45de4de6763b 100644 --- a/ext/opcache/tests/jit/qm_assign_undef_exception.phpt +++ b/ext/opcache/tests/jit/qm_assign_undef_exception.phpt @@ -17,5 +17,5 @@ try { echo $e->getMessage(), "\n"; } ?> ---EXPECT-- -Undefined variable $b +--EXPECTF-- +Undefined variable $b \ No newline at end of file diff --git a/ext/opcache/tests/jit/type_check_001.phpt b/ext/opcache/tests/jit/type_check_001.phpt index 028d2e8637e2..78936f197d5a 100644 --- a/ext/opcache/tests/jit/type_check_001.phpt +++ b/ext/opcache/tests/jit/type_check_001.phpt @@ -20,5 +20,5 @@ try { echo "Exception: " . $e->getMessage() . "\n"; } ?> ---EXPECT-- -Exception: Undefined variable $a +--EXPECTF-- +Exception: Undefined variable $a \ No newline at end of file diff --git a/ext/opcache/tests/opt/gh18107_1.phpt b/ext/opcache/tests/opt/gh18107_1.phpt index a2cf3162090c..67c5b4a102f8 100644 --- a/ext/opcache/tests/opt/gh18107_1.phpt +++ b/ext/opcache/tests/opt/gh18107_1.phpt @@ -28,19 +28,22 @@ $_main: ; (after optimizer) ; %s 0000 T1 = ISSET_ISEMPTY_CV (isset) CV0($badvar) -0001 JMPNZ T1 0006 +0001 JMPNZ T1 0007 0002 T3 = NEW 1 string("Exception") 0003 SEND_VAL%S string("Should happen") 1 0004 DO_FCALL -0005 THROW T3 -0006 JMP 0006 -0007 T6 = NEW 1 string("Exception") -0008 SEND_VAL%S string("Should not happen") 1 -0009 DO_FCALL -0010 THROW T6 -0011 FAST_RET T5 +0005 FLUSH_DEFERRED_DTORS +0006 THROW T3 +0007 FLUSH_DEFERRED_DTORS +0008 JMP 0008 +0009 T6 = NEW 1 string("Exception") +0010 SEND_VAL%S string("Should not happen") 1 +0011 DO_FCALL +0012 FLUSH_DEFERRED_DTORS +0013 THROW T6 +0014 FAST_RET T5 EXCEPTION TABLE: - 0006, -, 0007, 0011 + 0008, -, 0009, 0014 Fatal error: Uncaught Exception: Should happen in %s:%d Stack trace: diff --git a/ext/opcache/tests/opt/gh18107_2.phpt b/ext/opcache/tests/opt/gh18107_2.phpt index 74a709223e5a..3c883778a2c0 100644 --- a/ext/opcache/tests/opt/gh18107_2.phpt +++ b/ext/opcache/tests/opt/gh18107_2.phpt @@ -31,23 +31,28 @@ $_main: ; (after optimizer) ; %s 0000 T2 = ISSET_ISEMPTY_CV (isset) CV0($badvar) -0001 JMPNZ T2 0008 +0001 JMPNZ T2 0007 0002 T4 = NEW 1 string("Exception") 0003 SEND_VAL%S string("Should happen") 1 0004 DO_FCALL -0005 THROW T4 -0006 CV1($e) = CATCH string("Throwable") -0007 ECHO string("foo") -0008 T6 = FAST_CALL 0010 -0009 JMP 0015 -0010 T7 = NEW 1 string("Exception") -0011 SEND_VAL%S string("Should not happen") 1 -0012 DO_FCALL -0013 THROW T7 -0014 FAST_RET T6 -0015 RETURN int(1) +0005 FLUSH_DEFERRED_DTORS +0006 THROW T4 +0007 FLUSH_DEFERRED_DTORS +0008 FLUSH_DEFERRED_DTORS +0009 JMP 0012 +0010 CV1($e) = CATCH string("Throwable") +0011 ECHO string("foo") +0012 T6 = FAST_CALL 0014 +0013 JMP 0020 +0014 T7 = NEW 1 string("Exception") +0015 SEND_VAL%S string("Should not happen") 1 +0016 DO_FCALL +0017 FLUSH_DEFERRED_DTORS +0018 THROW T7 +0019 FAST_RET T6 +0020 RETURN int(1) EXCEPTION TABLE: - 0006, 0006, 0010, 0014 + 0008, 0010, 0014, 0019 Fatal error: Uncaught Exception: Should happen in %s:%d Stack trace: diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt index dfef3bb4839f..87121bae49de 100644 --- a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt @@ -85,8 +85,8 @@ array(1) { } bool(true) bool(true) -StatementWithPublicDestructor::__destruct Class derived from PDOStatement, with private constructor: +StatementWithPublicDestructor::__destruct bool(true) StatementWithPrivateConstructor::__construct object(StatementWithPrivateConstructor)#2 (1) { diff --git a/ext/pdo/tests/pdo_stmt_cyclic_references.phpt b/ext/pdo/tests/pdo_stmt_cyclic_references.phpt index 59d72c4b0d36..8d1c407da4a2 100644 --- a/ext/pdo/tests/pdo_stmt_cyclic_references.phpt +++ b/ext/pdo/tests/pdo_stmt_cyclic_references.phpt @@ -106,7 +106,7 @@ object(TestRow)#%d (4) { string(11) "Hello world" } Fetch into: -object(TestRow)#4 (4) { +object(TestRow)#5 (4) { ["id"]=> string(1) "1" ["val"]=> @@ -116,7 +116,7 @@ object(TestRow)#4 (4) { ["arg"]=> string(21) "I am being fetch into" } -object(TestRow)#4 (4) { +object(TestRow)#5 (4) { ["id"]=> string(1) "2" ["val"]=> @@ -126,7 +126,7 @@ object(TestRow)#4 (4) { ["arg"]=> string(21) "I am being fetch into" } -object(TestRow)#4 (4) { +object(TestRow)#5 (4) { ["id"]=> string(1) "3" ["val"]=> diff --git a/ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt b/ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt index bd3df73acba4..8302e15af089 100644 --- a/ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt +++ b/ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt @@ -65,5 +65,5 @@ pg_query($db, "DROP TABLE IF EXISTS pg_fetch_object_ctor_paths"); pg_fetch_object(): Argument #4 ($constructor_args) must be empty when the specified class (NoCtor) does not have a constructor caught: boom ctor sees: num=1, str=hello -SeesProps::__destruct called Ok +SeesProps::__destruct called diff --git a/ext/phar/tests/bug69720.phpt b/ext/phar/tests/bug69720.phpt index a6afe0f15e7f..8b99f23fa9a5 100644 --- a/ext/phar/tests/bug69720.phpt +++ b/ext/phar/tests/bug69720.phpt @@ -29,7 +29,7 @@ array(1) { ["whatever"]=> int(123) } -object(DateTime)#6 (3) { +object(DateTime)#%d (3) { ["date"]=> string(26) "2000-01-01 00:00:00.000000" ["timezone_type"]=> diff --git a/ext/phar/tests/tar/bug70417.phpt b/ext/phar/tests/tar/bug70417.phpt index 7bb6bbafbcfa..96c9119bca9a 100644 --- a/ext/phar/tests/tar/bug70417.phpt +++ b/ext/phar/tests/tar/bug70417.phpt @@ -23,4 +23,4 @@ $filename = __DIR__ . '/bug70417.tar'; @unlink("$filename.gz"); ?> --EXPECT-- -int(0) +int(2) diff --git a/ext/phar/tests/test_alias_unset.phpt b/ext/phar/tests/test_alias_unset.phpt index 3a11fbac6d5a..2120247a8ac9 100644 --- a/ext/phar/tests/test_alias_unset.phpt +++ b/ext/phar/tests/test_alias_unset.phpt @@ -37,7 +37,10 @@ $a = file_get_contents($pname . '/file1.txt'); // this fails because $fname2 ref --EXPECTF-- -Cannot open archive "%stest_alias_unset.2.phar.php", alias is already in use by existing archive -string(5) "first" +Warning: fopen(phar://%stest_alias_unset.phar.php/file1.txt): Failed to open stream: Cannot open archive "%stest_alias_unset.phar.php", alias is already in use by existing archive in %stest_alias_unset.php on line %d -Warning: file_get_contents(phar://%sfile1.txt): Failed to open stream: Cannot open archive "%stest_alias_unset.phar.php", alias is already in use by existing archive in %stest_alias_unset.php on line %d +Fatal error: Uncaught TypeError: fclose(): Argument #1 ($stream) must be of type resource, false given in %stest_alias_unset.php:%d +Stack trace: +#0 %stest_alias_unset.php(%d): fclose(false) +#1 {main} + thrown in %stest_alias_unset.php on line %d diff --git a/ext/spl/tests/SplFixedArray_immediate_gc.phpt b/ext/spl/tests/SplFixedArray_immediate_gc.phpt index cead2238c190..afebd03d626c 100644 --- a/ext/spl/tests/SplFixedArray_immediate_gc.phpt +++ b/ext/spl/tests/SplFixedArray_immediate_gc.phpt @@ -24,8 +24,8 @@ object(SplFixedArray)#2 (1) { } } Replacing -In destructor Dumping again +In destructor object(SplFixedArray)#2 (1) { [0]=> object(stdClass)#3 (0) { diff --git a/ext/spl/tests/gh12721.phpt b/ext/spl/tests/gh12721.phpt index 4310afcdd933..43e34dd053d9 100644 --- a/ext/spl/tests/gh12721.phpt +++ b/ext/spl/tests/gh12721.phpt @@ -43,7 +43,7 @@ object(SplFileInfo)#4 (2) { file1.gh12721 gh12721 file1.gh12721 -object(SplFileInfo)#3 (2) { +object(SplFileInfo)#5 (2) { ["pathName":"SplFileInfo":private]=> string(15) "%sfile1.gh12721" ["fileName":"SplFileInfo":private]=> diff --git a/ext/spl/tests/gh18274.phpt b/ext/spl/tests/gh18274.phpt new file mode 100644 index 000000000000..bc4f017d2c3b --- /dev/null +++ b/ext/spl/tests/gh18274.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-18274 (Assertion failure in SplFixedArray when an error handler runs during an undefined-variable write) +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught ArgumentCountError: func_get_args() expects exactly 0 arguments, 4 given in %s:%d +Stack trace: +#%d %A: func_get_args(%d, %s, %s, %d)%A +#%d {main} + thrown in %s on line %d diff --git a/ext/spl/tests/iterator_044.phpt b/ext/spl/tests/iterator_044.phpt index 74321194e098..27e35a903276 100644 --- a/ext/spl/tests/iterator_044.phpt +++ b/ext/spl/tests/iterator_044.phpt @@ -131,7 +131,7 @@ object(stdClass)#1 (0) { CachingIterator::offsetExists(): Argument #1 ($key) must be of type string, stdClass given CachingIterator::offsetGet(): Argument #1 ($key) must be of type string, stdClass given ===2=== -object(MyFoo)#2 (0) { +object(MyFoo)#8 (0) { } bool(true) int(1) diff --git a/ext/standard/array.c b/ext/standard/array.c index 2d1dd584906a..e7ca18e0a307 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -680,19 +680,20 @@ PHP_FUNCTION(natcasesort) typedef bucket_compare_func_t(*get_compare_function)(zend_long); static zend_always_inline void php_sort(INTERNAL_FUNCTION_PARAMETERS, get_compare_function get_cmp, bool renumber) { - HashTable *array; + zval *array; zend_long sort_type = PHP_SORT_REGULAR; bucket_compare_func_t cmp; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ARRAY_HT_EX(array, 0, 1) + Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) ZEND_PARSE_PARAMETERS_END(); cmp = get_cmp(sort_type); - zend_array_sort(array, cmp, renumber); + SEPARATE_ARRAY(array); + zend_array_sort(Z_ARRVAL_P(array), cmp, renumber); RETURN_TRUE; } @@ -911,22 +912,25 @@ PHP_FUNCTION(uksort) } /* }}} */ -static inline HashTable *get_ht_for_iap(zval *zv, bool separate) { +static inline HashTable *get_ht_for_iap(zval *zv, bool separate, zend_object **objp) { + *objp = NULL; if (EXPECTED(Z_TYPE_P(zv) == IS_ARRAY)) { return Z_ARRVAL_P(zv); } ZEND_ASSERT(Z_TYPE_P(zv) == IS_OBJECT); + zend_object *zobj = Z_OBJ_P(zv); + GC_ADDREF(zobj); php_error_docref(NULL, E_DEPRECATED, "Calling %s() on an object is deprecated", get_active_function_name()); - zend_object *zobj = Z_OBJ_P(zv); if (separate && zobj->properties && UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { GC_DELREF(zobj->properties); } zobj->properties = zend_array_dup(zobj->properties); } + *objp = zobj; return zobj->handlers->get_properties(zobj); } @@ -979,15 +983,19 @@ PHP_FUNCTION(end) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) ZEND_PARSE_PARAMETERS_END(); - HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); - if (zend_hash_num_elements(array) == 0) { + zend_object *iap_obj; + HashTable *array = get_ht_for_iap(array_zv, /* separate */ true, &iap_obj); + if (zend_hash_num_elements(array) != 0) { + zend_hash_internal_pointer_end(array); + if (USED_RET()) { + php_array_iter_return_current(return_value, array, false); + } + } else { /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ - RETURN_FALSE; + RETVAL_FALSE; } - zend_hash_internal_pointer_end(array); - - if (USED_RET()) { - php_array_iter_return_current(return_value, array, false); + if (iap_obj) { + OBJ_RELEASE(iap_obj); } } /* }}} */ @@ -1001,15 +1009,19 @@ PHP_FUNCTION(prev) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) ZEND_PARSE_PARAMETERS_END(); - HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); - if (zend_hash_num_elements(array) == 0) { + zend_object *iap_obj; + HashTable *array = get_ht_for_iap(array_zv, /* separate */ true, &iap_obj); + if (zend_hash_num_elements(array) != 0) { + zend_hash_move_backwards(array); + if (USED_RET()) { + php_array_iter_return_current(return_value, array, false); + } + } else { /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ - RETURN_FALSE; + RETVAL_FALSE; } - zend_hash_move_backwards(array); - - if (USED_RET()) { - php_array_iter_return_current(return_value, array, false); + if (iap_obj) { + OBJ_RELEASE(iap_obj); } } /* }}} */ @@ -1023,15 +1035,19 @@ PHP_FUNCTION(next) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) ZEND_PARSE_PARAMETERS_END(); - HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); - if (zend_hash_num_elements(array) == 0) { + zend_object *iap_obj; + HashTable *array = get_ht_for_iap(array_zv, /* separate */ true, &iap_obj); + if (zend_hash_num_elements(array) != 0) { + zend_hash_move_forward(array); + if (USED_RET()) { + php_array_iter_return_current(return_value, array, true); + } + } else { /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ - RETURN_FALSE; + RETVAL_FALSE; } - zend_hash_move_forward(array); - - if (USED_RET()) { - php_array_iter_return_current(return_value, array, true); + if (iap_obj) { + OBJ_RELEASE(iap_obj); } } /* }}} */ @@ -1045,15 +1061,19 @@ PHP_FUNCTION(reset) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) ZEND_PARSE_PARAMETERS_END(); - HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); - if (zend_hash_num_elements(array) == 0) { + zend_object *iap_obj; + HashTable *array = get_ht_for_iap(array_zv, /* separate */ true, &iap_obj); + if (zend_hash_num_elements(array) != 0) { + zend_hash_internal_pointer_reset(array); + if (USED_RET()) { + php_array_iter_return_current(return_value, array, true); + } + } else { /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ - RETURN_FALSE; + RETVAL_FALSE; } - zend_hash_internal_pointer_reset(array); - - if (USED_RET()) { - php_array_iter_return_current(return_value, array, true); + if (iap_obj) { + OBJ_RELEASE(iap_obj); } } /* }}} */ @@ -1067,8 +1087,12 @@ PHP_FUNCTION(current) Z_PARAM_ARRAY_OR_OBJECT(array_zv) ZEND_PARSE_PARAMETERS_END(); - HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); + zend_object *iap_obj; + HashTable *array = get_ht_for_iap(array_zv, /* separate */ false, &iap_obj); php_array_iter_return_current(return_value, array, true); + if (iap_obj) { + OBJ_RELEASE(iap_obj); + } } /* }}} */ @@ -1081,11 +1105,15 @@ PHP_FUNCTION(key) Z_PARAM_ARRAY_OR_OBJECT(array_zv) ZEND_PARSE_PARAMETERS_END(); - HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); + zend_object *iap_obj; + HashTable *array = get_ht_for_iap(array_zv, /* separate */ false, &iap_obj); zval *entry = php_array_iter_seek_current(array, true); if (EXPECTED(entry)) { zend_hash_get_current_key_zval(array, return_value); } + if (iap_obj) { + OBJ_RELEASE(iap_obj); + } } /* }}} */ diff --git a/ext/standard/tests/array/gh20042.phpt b/ext/standard/tests/array/gh20042.phpt new file mode 100644 index 000000000000..34ca982b2ae5 --- /dev/null +++ b/ext/standard/tests/array/gh20042.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-20042 (SEGV in array.c when the error handler reassigns the array during prev()) +--FILE-- + +--EXPECT-- +OK survived diff --git a/ext/standard/tests/array/sort/array_multisort_variation2.phpt b/ext/standard/tests/array/sort/array_multisort_variation2.phpt index b491b87bfda8..b3bdba7a63df 100644 --- a/ext/standard/tests/array/sort/array_multisort_variation2.phpt +++ b/ext/standard/tests/array/sort/array_multisort_variation2.phpt @@ -107,7 +107,7 @@ foreach($inputs as $key =>$value) { }; ?> ---EXPECT-- +--EXPECTF-- *** Testing array_multisort() : usage variation *** --int 0-- diff --git a/ext/standard/tests/class_object/get_class_methods_variation_001.phpt b/ext/standard/tests/class_object/get_class_methods_variation_001.phpt index f7b86a2977ac..71392b9f4dc1 100644 --- a/ext/standard/tests/class_object/get_class_methods_variation_001.phpt +++ b/ext/standard/tests/class_object/get_class_methods_variation_001.phpt @@ -109,25 +109,25 @@ get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid Arg value 0.5 get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, float given -Error: 2 - Array to string conversion Arg value Array -get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array -get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array -get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array -get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array +Error: 2 - Array to string conversion get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value @@ -169,4 +169,4 @@ get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid Arg value get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, null given -Done +Done \ No newline at end of file diff --git a/ext/standard/tests/class_object/get_parent_class_variation_002.phpt b/ext/standard/tests/class_object/get_parent_class_variation_002.phpt index 8faeff9dd8dc..eb951cfbfdce 100644 --- a/ext/standard/tests/class_object/get_parent_class_variation_002.phpt +++ b/ext/standard/tests/class_object/get_parent_class_variation_002.phpt @@ -112,25 +112,25 @@ get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid Arg value 0.5 get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, float given -Error: 2 - Array to string conversion Arg value Array -get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array -get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array -get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array -get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Error: 2 - Array to string conversion +get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value Array +Error: 2 - Array to string conversion get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given Arg value @@ -173,4 +173,4 @@ get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid Arg value get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, null given -Done +Done \ No newline at end of file diff --git a/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt b/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt index f03841dbac7d..7e74d8022d61 100644 --- a/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt +++ b/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt @@ -79,12 +79,12 @@ foreach($values as $value) { echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing is_subclass_of() : usage variations *** -Error: 2 - Undefined variable $undefined_var -Error: 2 - Undefined variable $unset_var - -Arg value 0 +%A +%A +%A +%A bool(false) Arg value 1 @@ -110,25 +110,25 @@ bool(false) Arg value 0.5 bool(false) -Error: 2 - Array to string conversion Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array +Error: 2 - Array to string conversion bool(false) Arg value diff --git a/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt b/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt index d045a4c1a915..fed9ef8c864d 100644 --- a/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt +++ b/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt @@ -79,12 +79,12 @@ foreach($values as $value) { echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing is_subclass_of() : usage variations *** -Error: 2 - Undefined variable $undefined_var -Error: 2 - Undefined variable $unset_var - -Arg value 0 +%A +%A +%A +%A bool(false) Arg value 1 @@ -110,25 +110,25 @@ bool(false) Arg value 0.5 bool(false) -Error: 2 - Array to string conversion Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array -bool(false) Error: 2 - Array to string conversion +bool(false) Arg value Array +Error: 2 - Array to string conversion bool(false) Arg value diff --git a/ext/standard/tests/class_object/method_exists_variation_001.phpt b/ext/standard/tests/class_object/method_exists_variation_001.phpt index d45d2652d11c..1761475ace66 100644 --- a/ext/standard/tests/class_object/method_exists_variation_001.phpt +++ b/ext/standard/tests/class_object/method_exists_variation_001.phpt @@ -83,10 +83,10 @@ echo "Done"; ?> --EXPECT-- *** Testing method_exists() : usage variations *** -Error: 2 - Undefined variable $undefined_var -Error: 2 - Undefined variable $unset_var Arg value 0 +Error: 2 - Undefined variable $undefined_var +Error: 2 - Undefined variable $unset_var method_exists(): Argument #1 ($object_or_class) must be of type object|string, int given Arg value 1 @@ -112,25 +112,25 @@ method_exists(): Argument #1 ($object_or_class) must be of type object|string, f Arg value 0.5 method_exists(): Argument #1 ($object_or_class) must be of type object|string, float given -Error: 2 - Array to string conversion Arg value Array -method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Error: 2 - Array to string conversion +method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Arg value Array -method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Error: 2 - Array to string conversion +method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Arg value Array -method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Error: 2 - Array to string conversion +method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Arg value Array -method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Error: 2 - Array to string conversion +method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Arg value Array +Error: 2 - Array to string conversion method_exists(): Argument #1 ($object_or_class) must be of type object|string, array given Arg value @@ -170,4 +170,4 @@ method_exists(): Argument #1 ($object_or_class) must be of type object|string, n Arg value method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given -Done +Done \ No newline at end of file diff --git a/ext/standard/tests/image/getimagesize_variation2.phpt b/ext/standard/tests/image/getimagesize_variation2.phpt index 045d9141a6bd..1728c668fab0 100644 --- a/ext/standard/tests/image/getimagesize_variation2.phpt +++ b/ext/standard/tests/image/getimagesize_variation2.phpt @@ -72,12 +72,12 @@ foreach($values as $key => $value) { }; ?> ---EXPECT-- +--EXPECTF-- *** Testing getimagesize() : usage variations *** -Error: 2 - Undefined variable $undefined_var -Error: 2 - Undefined variable $unset_var - --- Arg value 0 -- +%A +%A +%A +%A string(28) "4a46494600010201006000600000" -- Arg value 1 -- diff --git a/ext/zend_test/tests/observer_error_05.phpt b/ext/zend_test/tests/observer_error_05.phpt index d672e6405ec8..378bb00589ab 100644 --- a/ext/zend_test/tests/observer_error_05.phpt +++ b/ext/zend_test/tests/observer_error_05.phpt @@ -30,15 +30,15 @@ echo 'You should not see this.'; - - <{closure:%s:%d}> - - + + + <{closure:%s:%d}> + + Deprecated: Passing E_USER_ERROR to trigger_error() is deprecated since 8.4, throw an exception or call exit with a string message instead in %s on line %d Fatal error: Foo error in %s on line %d - - - + + diff --git a/ext/zend_test/tests/zend_object_init_with_constructor.phpt b/ext/zend_test/tests/zend_object_init_with_constructor.phpt index aa3ad7ee845a..2b08fc127a39 100644 --- a/ext/zend_test/tests/zend_object_init_with_constructor.phpt +++ b/ext/zend_test/tests/zend_object_init_with_constructor.phpt @@ -161,12 +161,12 @@ TypeError: TestUserWithConstructorArgs::__construct(): Argument #1 ($int_param) Error: Unknown named parameter $unused_param object(TestUserWithConstructorArgs)#%d (0) { } -Destructor for TestUserWithConstructorArgs Passing too many args to constructor +Destructor for TestUserWithConstructorArgs object(TestUserWithConstructorArgs)#%d (0) { } -Destructor for TestUserWithConstructorArgs Testing class with defined constructor and no params +Destructor for TestUserWithConstructorArgs object(TestUserWithConstructorNoParams)#%d (0) { } Destructor for TestUserWithConstructorNoParams diff --git a/ext/zend_test/tests/zend_object_init_with_constructor_classes_without_constructor.phpt b/ext/zend_test/tests/zend_object_init_with_constructor_classes_without_constructor.phpt index 1adaaafaa195..fd28fef08e66 100644 --- a/ext/zend_test/tests/zend_object_init_with_constructor_classes_without_constructor.phpt +++ b/ext/zend_test/tests/zend_object_init_with_constructor_classes_without_constructor.phpt @@ -105,13 +105,13 @@ Userland class: Using new: object(TestUserWithoutConstructor)#1 (0) { } -Destructor for TestUserWithoutConstructor Using zend_object_init_with_constructor(): -object(TestUserWithoutConstructor)#1 (0) { -} Destructor for TestUserWithoutConstructor +object(TestUserWithoutConstructor)#2 (0) { +} Internal class: Using new: +Destructor for TestUserWithoutConstructor object(_ZendTestMagicCall)#1 (0) { } Using zend_object_init_with_constructor(): @@ -123,17 +123,17 @@ Userland class: Using new: object(TestUserWithoutConstructor)#1 (0) { } -Destructor for TestUserWithoutConstructor Using zend_object_init_with_constructor(): -object(TestUserWithoutConstructor)#1 (0) { -} Destructor for TestUserWithoutConstructor +object(TestUserWithoutConstructor)#2 (0) { +} Internal class: Using new: -object(_ZendTestMagicCall)#1 (0) { +Destructor for TestUserWithoutConstructor +object(_ZendTestMagicCall)#2 (0) { } Using zend_object_init_with_constructor(): -object(_ZendTestMagicCall)#1 (0) { +object(_ZendTestMagicCall)#2 (0) { } #### Passing extra named args #### diff --git a/ext/zip/tests/ZipArchive_destruct.phpt b/ext/zip/tests/ZipArchive_destruct.phpt index 7e3ef6c5dae4..52ae2c5ff55d 100644 --- a/ext/zip/tests/ZipArchive_destruct.phpt +++ b/ext/zip/tests/ZipArchive_destruct.phpt @@ -24,5 +24,10 @@ $leak->addFromString('test', 'test'); $file = __DIR__ . '/ZipArchive_destruct.zip'; @unlink($file); ?> ---EXPECT-- -===DONE=== +--EXPECTF-- +Warning: Undefined variable $leak in %s on line 12 + +Fatal error: Uncaught Error: Call to a member function open() on null in %s:12 +Stack trace: +#0 {main} + thrown in %s on line 12 diff --git a/tests/classes/bug27468.phpt b/tests/classes/bug27468.phpt index d590683c82cf..1474f6d453b0 100644 --- a/tests/classes/bug27468.phpt +++ b/tests/classes/bug27468.phpt @@ -11,7 +11,7 @@ new foo(); echo 'OK'; ?> --EXPECTF-- +OK Warning: Undefined property: foo::$x in %s on line %d Warning: foreach() argument must be of type array|object, null given in %sbug27468.php on line 4 -OK diff --git a/tests/classes/ctor_dtor_inheritance.phpt b/tests/classes/ctor_dtor_inheritance.phpt index 5dbb1747065b..4e6541d83f8e 100644 --- a/tests/classes/ctor_dtor_inheritance.phpt +++ b/tests/classes/ctor_dtor_inheritance.phpt @@ -59,12 +59,12 @@ base Object ( [name] => base ) +Testing class derived base::__destruct base Object ( [name] => base ) -Testing class derived derived Object ( [name] => init @@ -82,6 +82,7 @@ derived Object [name] => derived [other] => other ) +Done base::__destruct derived Object ( @@ -94,4 +95,3 @@ derived Object [name] => derived [other] => other ) -Done diff --git a/tests/classes/destructor_and_exceptions.phpt b/tests/classes/destructor_and_exceptions.phpt index 0f51a21a09d0..666fe6cb2eb4 100644 --- a/tests/classes/destructor_and_exceptions.phpt +++ b/tests/classes/destructor_and_exceptions.phpt @@ -54,5 +54,6 @@ catch(FatalException $e) FailClass::__destruct Caught: FailClass FatalException::__construct +Done: FatalException::__construct FailClass::__destruct Caught Exception: FailClass diff --git a/tests/classes/destructor_inheritance.phpt b/tests/classes/destructor_inheritance.phpt index c527c04b4fc1..06f7c9d9fe0f 100644 --- a/tests/classes/destructor_inheritance.phpt +++ b/tests/classes/destructor_inheritance.phpt @@ -23,5 +23,4 @@ echo 'Done'; ?> --EXPECT-- base::__construct -base::__destruct -Done +Donebase::__destruct diff --git a/tests/classes/destructor_visibility_001.phpt b/tests/classes/destructor_visibility_001.phpt index 6fee6e3be742..61912e54e1ad 100644 --- a/tests/classes/destructor_visibility_001.phpt +++ b/tests/classes/destructor_visibility_001.phpt @@ -19,7 +19,9 @@ unset($obj); ?> ===DONE=== --EXPECTF-- +===DONE=== + Fatal error: Uncaught Error: Call to private Derived::__destruct() from global scope in %s:%d Stack trace: #0 {main} - thrown in %sdestructor_visibility_001.php on line %d + thrown in %s on line %d diff --git a/tests/classes/factory_and_singleton_005.phpt b/tests/classes/factory_and_singleton_005.phpt index 41914bf0e087..27779146d72e 100644 --- a/tests/classes/factory_and_singleton_005.phpt +++ b/tests/classes/factory_and_singleton_005.phpt @@ -14,7 +14,9 @@ $obj = NULL; echo "Done\n"; ?> --EXPECTF-- +Done + Fatal error: Uncaught Error: Call to protected test::__destruct() from global scope in %s:%d Stack trace: #0 {main} - thrown in %sfactory_and_singleton_005.php on line %d + thrown in %s on line %d diff --git a/tests/classes/factory_and_singleton_006.phpt b/tests/classes/factory_and_singleton_006.phpt index 596a0792cd09..bcc57c095766 100644 --- a/tests/classes/factory_and_singleton_006.phpt +++ b/tests/classes/factory_and_singleton_006.phpt @@ -14,7 +14,9 @@ $obj = NULL; echo "Done\n"; ?> --EXPECTF-- +Done + Fatal error: Uncaught Error: Call to private test::__destruct() from global scope in %s:%d Stack trace: #0 {main} - thrown in %sfactory_and_singleton_006.php on line %d + thrown in %s on line %d diff --git a/tests/classes/iterators_002.phpt b/tests/classes/iterators_002.phpt index 71f252dc0ede..08e11b12551a 100644 --- a/tests/classes/iterators_002.phpt +++ b/tests/classes/iterators_002.phpt @@ -106,6 +106,6 @@ double:2:0 c_iter::__destruct c_iter::next c_iter::valid = false +Done c_iter::__destruct c::__destruct -Done diff --git a/tests/classes/tostring_002.phpt b/tests/classes/tostring_002.phpt index 3977ad883f25..0ab2378f1003 100644 --- a/tests/classes/tostring_002.phpt +++ b/tests/classes/tostring_002.phpt @@ -24,6 +24,6 @@ $o = new Test; ?> ====DONE==== --EXPECT-- -Hello ====DONE==== Hello +Hello diff --git a/tests/lang/bug22592.phpt b/tests/lang/bug22592.phpt index 24b5f50fdf5a..2505b2ff7212 100644 --- a/tests/lang/bug22592.phpt +++ b/tests/lang/bug22592.phpt @@ -39,12 +39,12 @@ var_dump($result); string(5) "* *-*" string(7) "* *-* *" string(7) "*4*-* *" -[Only the first byte will be assigned to the string offset] string(7) "*4*s* *" +[Only the first byte will be assigned to the string offset] string(8) "*4*s* *0" string(8) "*-*-* *0" -[Only the first byte will be assigned to the string offset] string(8) "*-*s*s*0" +[Only the first byte will be assigned to the string offset] string(8) "4-4s4s*0" string(9) "4-4s4s505" string(9) "454s4s505" diff --git a/tests/lang/bug25547.phpt b/tests/lang/bug25547.phpt index 53b951fd4543..49bdb5e75115 100644 --- a/tests/lang/bug25547.phpt +++ b/tests/lang/bug25547.phpt @@ -22,9 +22,9 @@ print_r($output); echo "Done"; ?> --EXPECT-- -handler(Undefined array key "foo") Array ( [foo] => 1 ) +handler(Undefined array key "foo") Done diff --git a/tests/lang/bug25922.phpt b/tests/lang/bug25922.phpt index 4927bfea776c..41aa72ae35d6 100644 --- a/tests/lang/bug25922.phpt +++ b/tests/lang/bug25922.phpt @@ -19,6 +19,6 @@ function test() test(); ?> --EXPECT-- +Undefined index here: '' Undefined variable $data Trying to access array offset on null -Undefined index here: ''