diff --git a/Zend/Optimizer/zend_call_graph.c b/Zend/Optimizer/zend_call_graph.c index 1f290c5e00470..aa78fa9f4c838 100644 --- a/Zend/Optimizer/zend_call_graph.c +++ b/Zend/Optimizer/zend_call_graph.c @@ -106,6 +106,7 @@ ZEND_API int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_ case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: + case ZEND_DO_FCALL_PARTIAL: func_info->flags |= ZEND_FUNC_HAS_CALLS; if (call_info) { call_info->caller_call_opline = opline; @@ -122,6 +123,7 @@ ZEND_API int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_ case ZEND_SEND_VAR_NO_REF: case ZEND_SEND_VAR_NO_REF_EX: case ZEND_SEND_USER: + case ZEND_SEND_PLACEHOLDER: if (call_info) { if (opline->op2_type == IS_CONST) { call_info->named_args = 1; diff --git a/Zend/tests/partial_application/compile_errors_001.phpt b/Zend/tests/partial_application/compile_errors_001.phpt new file mode 100644 index 0000000000000..73eafa4e2cd45 --- /dev/null +++ b/Zend/tests/partial_application/compile_errors_001.phpt @@ -0,0 +1,9 @@ +--TEST-- +Partial application compile errors: multiple ... +--FILE-- + +--EXPECTF-- +Fatal error: Variadic placeholder may only appear once in %s on line %d + diff --git a/Zend/tests/partial_application/compile_errors_002.phpt b/Zend/tests/partial_application/compile_errors_002.phpt new file mode 100644 index 0000000000000..29a346ec88a5f --- /dev/null +++ b/Zend/tests/partial_application/compile_errors_002.phpt @@ -0,0 +1,9 @@ +--TEST-- +Partial application compile errors: only named arguments after ... +--FILE-- + +--EXPECTF-- +Fatal error: Only named arguments may follow variadic placeholder in %s on line %d + diff --git a/Zend/tests/partial_application/compile_errors_003.phpt b/Zend/tests/partial_application/compile_errors_003.phpt new file mode 100644 index 0000000000000..6d833b7ef1b61 --- /dev/null +++ b/Zend/tests/partial_application/compile_errors_003.phpt @@ -0,0 +1,9 @@ +--TEST-- +Partial application compile errors: named arguments must come after placeholder +--FILE-- + +--EXPECTF-- +Fatal error: Named arguments must come after all placeholders in %s on line %d + diff --git a/Zend/tests/partial_application/compile_errors_004.phpt b/Zend/tests/partial_application/compile_errors_004.phpt new file mode 100644 index 0000000000000..efd544282c2e9 --- /dev/null +++ b/Zend/tests/partial_application/compile_errors_004.phpt @@ -0,0 +1,8 @@ +--TEST-- +Partial application compile errors: named arguments must come after variadic placeholder +--FILE-- + +--EXPECTF-- +Fatal error: Named arguments must come after all placeholders in %s on line %d diff --git a/Zend/tests/partial_application/compile_errors_005.phpt b/Zend/tests/partial_application/compile_errors_005.phpt new file mode 100644 index 0000000000000..b6a898008617b --- /dev/null +++ b/Zend/tests/partial_application/compile_errors_005.phpt @@ -0,0 +1,9 @@ +--TEST-- +Partial application compile errors: follow variadic with un-named arg +--FILE-- + +--EXPECTF-- +Fatal error: Only named arguments may follow variadic placeholder in %s on line %d + diff --git a/Zend/tests/partial_application/compile_errors_006.phpt b/Zend/tests/partial_application/compile_errors_006.phpt new file mode 100644 index 0000000000000..21ad1a954e929 --- /dev/null +++ b/Zend/tests/partial_application/compile_errors_006.phpt @@ -0,0 +1,9 @@ +--TEST-- +Partial application compile errors: mix application with unpack (placeholder after) +--FILE-- + "bar"], ...); +?> +--EXPECTF-- +Fatal error: Cannot combine partial application and unpacking %s on line %d + diff --git a/Zend/tests/partial_application/compile_errors_007.phpt b/Zend/tests/partial_application/compile_errors_007.phpt new file mode 100644 index 0000000000000..5cc881ebf60f5 --- /dev/null +++ b/Zend/tests/partial_application/compile_errors_007.phpt @@ -0,0 +1,9 @@ +--TEST-- +Partial application compile errors: mix application with unpack (placeholder before) +--FILE-- + "bar"]); +?> +--EXPECTF-- +Fatal error: Cannot combine partial application and unpacking %s on line %d + diff --git a/Zend/tests/partial_application/errors_001.phpt b/Zend/tests/partial_application/errors_001.phpt new file mode 100644 index 0000000000000..d6e37051c1eca --- /dev/null +++ b/Zend/tests/partial_application/errors_001.phpt @@ -0,0 +1,38 @@ +--TEST-- +Partial application errors: placeholder count errors +--FILE-- +getMessage()); +} + +try { + foo(?, ?, ?, ?); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +try { + property_exists(?); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +try { + usleep(?, ?); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} +?> +--EXPECTF-- +not enough arguments or placeholders for application of foo, 1 given and exactly 3 expected, declared in %s on line 2 +too many arguments or placeholders for application of foo, 4 given and a maximum of 3 expected, declared in %s on line 2 +not enough arguments or placeholders for application of property_exists, 1 given and exactly 2 expected +too many arguments or placeholders for application of usleep, 2 given and a maximum of 1 expected + diff --git a/Zend/tests/partial_application/errors_002.phpt b/Zend/tests/partial_application/errors_002.phpt new file mode 100644 index 0000000000000..2f852348fb1fd --- /dev/null +++ b/Zend/tests/partial_application/errors_002.phpt @@ -0,0 +1,17 @@ +--TEST-- +Partial application errors: named parameter overwrites placeholder +--FILE-- +getMessage()); +} +?> +--EXPECT-- +Named parameter $a overwrites previous placeholder + diff --git a/Zend/tests/partial_application/errors_003.phpt b/Zend/tests/partial_application/errors_003.phpt new file mode 100644 index 0000000000000..0ce69bc9ad65b --- /dev/null +++ b/Zend/tests/partial_application/errors_003.phpt @@ -0,0 +1,78 @@ +--TEST-- +Partial application errors: missing parameters +--FILE-- +getMessage()); +} + +$foo = foo(?, ?); + +try { + $foo(1); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +$bar = bar(?, ?, ...); + +try { + $bar(1); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +class Foo { + public function bar($a, ...$b) {} +} + +$foo = new Foo; + +$bar = $foo->bar(?); + +try { + $bar(); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +$usleep = usleep(...); + +try { + $usleep(); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +$usleep = usleep(?); + +try { + $usleep(); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +try { + $usleep(1, 2); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} +?> +--EXPECTF-- +not enough arguments for application of foo, 0 given and exactly 1 expected, declared in %s on line 8 +not enough arguments for application of foo, 1 given and exactly 2 expected, declared in %s on line 16 +not enough arguments for application of bar, 1 given and at least 2 expected, declared in %s on line 24 +not enough arguments for application of Foo::bar, 0 given and exactly 1 expected, declared in %s on line 38 +not enough arguments for implementation of usleep, 0 given and exactly 1 expected +not enough arguments for application of usleep, 0 given and exactly 1 expected +too many arguments for application of usleep, 2 given and a maximum of 1 expected diff --git a/Zend/tests/partial_application/export_001.phpt b/Zend/tests/partial_application/export_001.phpt new file mode 100644 index 0000000000000..a4af669148b14 --- /dev/null +++ b/Zend/tests/partial_application/export_001.phpt @@ -0,0 +1,14 @@ +--TEST-- +Partial application ast export +--INI-- +assert.exception=1 +--FILE-- +getMessage()); +} +?> +--EXPECT-- +assert(0 && foo(?) && foo(...)) diff --git a/Zend/tests/partial_application/extra_collect_001.phpt b/Zend/tests/partial_application/extra_collect_001.phpt new file mode 100644 index 0000000000000..c5b44576f0e15 --- /dev/null +++ b/Zend/tests/partial_application/extra_collect_001.phpt @@ -0,0 +1,50 @@ +--TEST-- +Partial application named parameters: extra collection +--FILE-- + +--EXPECT-- +array(3) { + ["foo"]=> + string(3) "foo" + ["bar"]=> + string(3) "bar" + ["baz"]=> + string(3) "baz" +} +array(2) { + ["bar"]=> + string(3) "bar" + ["baz"]=> + string(3) "baz" +} +array(2) { + ["foo"]=> + string(3) "foo" + ["bar"]=> + string(3) "bar" +} + diff --git a/Zend/tests/partial_application/factory_001.phpt b/Zend/tests/partial_application/factory_001.phpt new file mode 100644 index 0000000000000..ad34aebd027f1 --- /dev/null +++ b/Zend/tests/partial_application/factory_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +Partial application factory: pass +--FILE-- + +--EXPECTF-- +OK +Foo::__destruct +Foo::__destruct diff --git a/Zend/tests/partial_application/factory_002.phpt b/Zend/tests/partial_application/factory_002.phpt new file mode 100644 index 0000000000000..2b94ead0379a1 --- /dev/null +++ b/Zend/tests/partial_application/factory_002.phpt @@ -0,0 +1,30 @@ +--TEST-- +Partial application factory: normal +--FILE-- + +--EXPECTF-- +Foo::__construct +Foo::__construct +OK +Foo::__destruct +Foo::__destruct diff --git a/Zend/tests/partial_application/factory_003.phpt b/Zend/tests/partial_application/factory_003.phpt new file mode 100644 index 0000000000000..fb752b299b6c5 --- /dev/null +++ b/Zend/tests/partial_application/factory_003.phpt @@ -0,0 +1,24 @@ +--TEST-- +Partial application factory: exception +--FILE-- +getMessage()); +} +?> +--EXPECT-- +boo diff --git a/Zend/tests/partial_application/factory_004.phpt b/Zend/tests/partial_application/factory_004.phpt new file mode 100644 index 0000000000000..dd46d203aacde --- /dev/null +++ b/Zend/tests/partial_application/factory_004.phpt @@ -0,0 +1,18 @@ +--TEST-- +Partial application factory object properties initialization +--FILE-- + +--EXPECTF-- +object(Foo)#%d (1) { + ["arg"]=> + int(1) +} + diff --git a/Zend/tests/partial_application/magic_001.phpt b/Zend/tests/partial_application/magic_001.phpt new file mode 100644 index 0000000000000..db8770fbdc41e --- /dev/null +++ b/Zend/tests/partial_application/magic_001.phpt @@ -0,0 +1,76 @@ +--TEST-- +Partial application magic: __call +--FILE-- +method(?); + +echo (string) new ReflectionFunction($bar); + +try { + $bar(); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +try { + $bar(1, 2); +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +$bar(1); + +$bar = $foo->method(?, ...); + +echo (string) new ReflectionFunction($bar); + +$bar(10); + +$bar = $foo->method(...); + +echo (string) new ReflectionFunction($bar); + +$bar(100); +?> +--EXPECTF-- +Method [ partial public method method ] { + @@ %s 12 - 12 + + - Parameters [1] { + Parameter #0 [ $args ] + } +} +not enough arguments for application of Foo::method, 0 given and exactly 1 expected, declared in %s on line 12 +too many arguments for application of Foo::method, 2 given and a maximum of 1 expected, declared in %s on line 12 +Foo::method +int(1) +Method [ partial public method method ] { + @@ %s 30 - 30 + + - Parameters [2] { + Parameter #0 [ $args ] + Parameter #1 [ ...$args ] + } +} +Foo::method +int(10) +Method [ partial public method method ] { + @@ %s 36 - 36 + + - Parameters [1] { + Parameter #0 [ ...$args ] + } +} +Foo::method +int(100) + diff --git a/Zend/tests/partial_application/magic_002.phpt b/Zend/tests/partial_application/magic_002.phpt new file mode 100644 index 0000000000000..e137c87b7814a --- /dev/null +++ b/Zend/tests/partial_application/magic_002.phpt @@ -0,0 +1,60 @@ +--TEST-- +Partial application magic: __callStatic +--FILE-- + +--EXPECTF-- +Method [ partial static public method method ] { + @@ %s 10 - 10 + + - Parameters [1] { + Parameter #0 [ $args ] + } +} +Foo::method +int(1) +Method [ partial static public method method ] { + @@ %s 16 - 16 + + - Parameters [2] { + Parameter #0 [ $args ] + Parameter #1 [ ...$args ] + } +} +Foo::method +int(10) +Method [ partial static public method method ] { + @@ %s 22 - 22 + + - Parameters [1] { + Parameter #0 [ ...$args ] + } +} +Foo::method +int(100) + diff --git a/Zend/tests/partial_application/magic_003.phpt b/Zend/tests/partial_application/magic_003.phpt new file mode 100644 index 0000000000000..a46fb5df226bf --- /dev/null +++ b/Zend/tests/partial_application/magic_003.phpt @@ -0,0 +1,13 @@ +--TEST-- +Partial application magic trampoline release unused +--FILE-- + +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/magic_004.phpt b/Zend/tests/partial_application/magic_004.phpt new file mode 100644 index 0000000000000..4c6f47ef366fd --- /dev/null +++ b/Zend/tests/partial_application/magic_004.phpt @@ -0,0 +1,13 @@ +--TEST-- +Partial application magic trampoline release used +--FILE-- + +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/magic_005.phpt b/Zend/tests/partial_application/magic_005.phpt new file mode 100644 index 0000000000000..ab66f9448e2c1 --- /dev/null +++ b/Zend/tests/partial_application/magic_005.phpt @@ -0,0 +1,33 @@ +--TEST-- +Partial application magic null ptr deref in arginfo +--FILE-- +method(?); +var_dump($bar); +?> +--EXPECTF-- +object(Closure)#%d (3) { + ["this"]=> + object(Foo)#%d (0) { + } + ["parameter"]=> + array(1) { + ["$args"]=> + string(10) "" + } + ["args"]=> + array(1) { + ["args"]=> + array(1) { + [0]=> + NULL + } + } +} + diff --git a/Zend/tests/partial_application/reflection_001.phpt b/Zend/tests/partial_application/reflection_001.phpt new file mode 100644 index 0000000000000..e9f77a778687b --- /dev/null +++ b/Zend/tests/partial_application/reflection_001.phpt @@ -0,0 +1,62 @@ +--TEST-- +Partial application reflection: required parameters +--FILE-- + +--EXPECTF-- +Function [ partial function foo ] { + @@ %s 6 - 6 + + - Parameters [3] { + Parameter #0 [ $a = 1 ] + Parameter #1 [ $b = 5 ] + Parameter #2 [ $c = 10 ] + } +} +Function [ partial function foo ] { + @@ %s 10 - 10 + + - Parameters [3] { + Parameter #0 [ $a ] + Parameter #1 [ $b = 5 ] + Parameter #2 [ $c = 10 ] + } +} +Function [ partial function foo ] { + @@ %s 14 - 14 + + - Parameters [3] { + Parameter #0 [ $a ] + Parameter #1 [ $b ] + Parameter #2 [ $c = 10 ] + } +} +Function [ partial function foo ] { + @@ %s 18 - 18 + + - Parameters [3] { + Parameter #0 [ $a ] + Parameter #1 [ $b ] + Parameter #2 [ $c ] + } +} + diff --git a/Zend/tests/partial_application/reflection_002.phpt b/Zend/tests/partial_application/reflection_002.phpt new file mode 100644 index 0000000000000..dbdbc56e815a2 --- /dev/null +++ b/Zend/tests/partial_application/reflection_002.phpt @@ -0,0 +1,57 @@ +--TEST-- +Partial application reflection: variadics +--FILE-- + +--EXPECTF-- +Function [ partial function foo ] { + @@ %s 6 - 6 + + - Parameters [1] { + Parameter #0 [ $a ] + } +} +Function [ partial function foo ] { + @@ %s 10 - 10 + + - Parameters [2] { + Parameter #0 [ $a ] + Parameter #1 [ ...$b ] + } +} +Function [ partial function foo ] { + @@ %s 14 - 14 + + - Parameters [2] { + Parameter #0 [ $a ] + Parameter #1 [ $b ] + } +} +Function [ partial function foo ] { + @@ %s 18 - 18 + + - Parameters [3] { + Parameter #0 [ $a ] + Parameter #1 [ $b ] + Parameter #2 [ $b ] + } +} diff --git a/Zend/tests/partial_application/reflection_003.phpt b/Zend/tests/partial_application/reflection_003.phpt new file mode 100644 index 0000000000000..cd117c94ecf60 --- /dev/null +++ b/Zend/tests/partial_application/reflection_003.phpt @@ -0,0 +1,41 @@ +--TEST-- +Partial application reflection: internal with variadics +--FILE-- + +--EXPECTF-- +Function [ partial function sprintf ] { + + - Parameters [1] { + Parameter #0 [ string $format ] + } + - Return [ string ] +} +Function [ partial function sprintf ] { + + - Parameters [2] { + Parameter #0 [ string $format ] + Parameter #1 [ mixed ...$values ] + } + - Return [ string ] +} +Function [ partial function sprintf ] { + + - Parameters [2] { + Parameter #0 [ string $format ] + Parameter #1 [ mixed $values ] + } + - Return [ string ] +} + diff --git a/Zend/tests/partial_application/return_type_001.phpt b/Zend/tests/partial_application/return_type_001.phpt new file mode 100644 index 0000000000000..af7826ff160ad --- /dev/null +++ b/Zend/tests/partial_application/return_type_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +Partial application return type +--FILE-- + +--EXPECTF-- +Function [ partial function foo ] { + @@ %s 4 - 4 + + - Parameters [0] { + } + - Return [ array ] +} + diff --git a/Zend/tests/partial_application/static_method_001.phpt b/Zend/tests/partial_application/static_method_001.phpt new file mode 100644 index 0000000000000..a690873499ba0 --- /dev/null +++ b/Zend/tests/partial_application/static_method_001.phpt @@ -0,0 +1,18 @@ +--TEST-- +Partial application static method +--FILE-- + +--EXPECTF-- +Foo::method diff --git a/Zend/tests/partial_application/statics_001.phpt b/Zend/tests/partial_application/statics_001.phpt new file mode 100644 index 0000000000000..c4edc8eaceb7a --- /dev/null +++ b/Zend/tests/partial_application/statics_001.phpt @@ -0,0 +1,22 @@ +--TEST-- +Partial application static variables shared +--FILE-- + +--EXPECTF-- +OK diff --git a/Zend/tests/partial_application/this_001.phpt b/Zend/tests/partial_application/this_001.phpt new file mode 100644 index 0000000000000..2113d9e78a0fd --- /dev/null +++ b/Zend/tests/partial_application/this_001.phpt @@ -0,0 +1,22 @@ +--TEST-- +Partial application this +--FILE-- +method(...); + +$baz = $bar(...); + +var_dump($baz()); +?> +--EXPECTF-- +object(Foo)#%d (0) { +} + diff --git a/Zend/tests/partial_application/variation_apply_002.phpt b/Zend/tests/partial_application/variation_apply_002.phpt new file mode 100644 index 0000000000000..abdf24788081a --- /dev/null +++ b/Zend/tests/partial_application/variation_apply_002.phpt @@ -0,0 +1,18 @@ +--TEST-- +Partial application variation type +--FILE-- + +--EXPECT-- +Foo::__construct diff --git a/Zend/tests/partial_application/variation_bind_001.phpt b/Zend/tests/partial_application/variation_bind_001.phpt new file mode 100644 index 0000000000000..4b064d024ffc4 --- /dev/null +++ b/Zend/tests/partial_application/variation_bind_001.phpt @@ -0,0 +1,74 @@ +--TEST-- +Partial application variation binding +--FILE-- +method(?, new Param); + +$closure(1); + +var_dump($closure); + +$bound = $closure->bindTo(new Foo); + +$bound(1); + +var_dump($bound); +?> +--EXPECTF-- +Bar: 1, Param +object(Closure)#%d (3) { + ["this"]=> + object(Bar)#%d (0) { + } + ["parameter"]=> + array(1) { + ["$a"]=> + string(10) "" + } + ["args"]=> + array(2) { + ["a"]=> + NULL + ["b"]=> + object(Param)#%d (0) { + } + } +} +Foo: 1, Param +object(Closure)#%d (3) { + ["this"]=> + object(Foo)#%d (0) { + } + ["parameter"]=> + array(1) { + ["$a"]=> + string(10) "" + } + ["args"]=> + array(2) { + ["a"]=> + NULL + ["b"]=> + object(Param)#%d (0) { + } + } +} + diff --git a/Zend/tests/partial_application/variation_bind_002.phpt b/Zend/tests/partial_application/variation_bind_002.phpt new file mode 100644 index 0000000000000..ccd3134e2683c --- /dev/null +++ b/Zend/tests/partial_application/variation_bind_002.phpt @@ -0,0 +1,67 @@ +--TEST-- +Partial application variation binding static +--FILE-- +bindTo(null, Foo::class); + +$bound(1); + +var_dump($bound); +?> +--EXPECTF-- +Bar: 1, Param +object(Closure)#%d (2) { + ["parameter"]=> + array(1) { + ["$a"]=> + string(10) "" + } + ["args"]=> + array(2) { + ["a"]=> + NULL + ["b"]=> + object(Param)#%d (0) { + } + } +} +Foo: 1, Param +object(Closure)#%d (2) { + ["parameter"]=> + array(1) { + ["$a"]=> + string(10) "" + } + ["args"]=> + array(2) { + ["a"]=> + NULL + ["b"]=> + object(Param)#%d (0) { + } + } +} + diff --git a/Zend/tests/partial_application/variation_call_001.phpt b/Zend/tests/partial_application/variation_call_001.phpt new file mode 100644 index 0000000000000..099ca9c50fc08 --- /dev/null +++ b/Zend/tests/partial_application/variation_call_001.phpt @@ -0,0 +1,32 @@ +--TEST-- +Partial application variation call +--FILE-- +method(?, new Param); + +$closure(1); + +$closure->call( + new Foo(), 10); +?> +--EXPECT-- +Bar: 1, Param +Foo: 10, Param diff --git a/Zend/tests/partial_application/variation_closure_001.phpt b/Zend/tests/partial_application/variation_closure_001.phpt new file mode 100644 index 0000000000000..c9e7ea96f55d8 --- /dev/null +++ b/Zend/tests/partial_application/variation_closure_001.phpt @@ -0,0 +1,19 @@ +--TEST-- +Partial application variation closure +--FILE-- + +--EXPECTF-- +Function [ partial function {closure} ] { + @@ %s 6 - 6 + + - Parameters [1] { + Parameter #0 [ $b ] + } +} + diff --git a/Zend/tests/partial_application/variation_closure_002.phpt b/Zend/tests/partial_application/variation_closure_002.phpt new file mode 100644 index 0000000000000..572c8bd0a674f --- /dev/null +++ b/Zend/tests/partial_application/variation_closure_002.phpt @@ -0,0 +1,23 @@ +--TEST-- +Partial application variation closure __invoke +--FILE-- +__invoke(1, ?); + +echo (string) new ReflectionFunction($function); + +$function(10); +?> +--EXPECTF-- +Method [ partial public method __invoke ] { + + - Parameters [1] { + Parameter #0 [ $b ] + } +} +int(1) +int(10) diff --git a/Zend/tests/partial_application/variation_closure_003.phpt b/Zend/tests/partial_application/variation_closure_003.phpt new file mode 100644 index 0000000000000..f1363efaf7b32 --- /dev/null +++ b/Zend/tests/partial_application/variation_closure_003.phpt @@ -0,0 +1,42 @@ +--TEST-- +Partial application variation closure __invoke with this +--FILE-- +bar(); + +$function = $closure->__invoke(1, ?); + +echo (string) new ReflectionFunction($function); + +var_dump($function(10)); +?> +--EXPECTF-- +Method [ partial public method __invoke ] { + + - Parameters [1] { + Parameter #0 [ $b ] + } +} +array(2) { + [0]=> + object(Foo)#1 (0) { + } + [1]=> + array(2) { + [0]=> + int(1) + [1]=> + int(10) + } +} + diff --git a/Zend/tests/partial_application/variation_debug_001.phpt b/Zend/tests/partial_application/variation_debug_001.phpt new file mode 100644 index 0000000000000..6981885c09e7d --- /dev/null +++ b/Zend/tests/partial_application/variation_debug_001.phpt @@ -0,0 +1,36 @@ +--TEST-- +Partial application variation debug user +--FILE-- + +--EXPECTF-- +object(Closure)#%d (2) { + ["parameter"]=> + array(1) { + ["$a"]=> + string(10) "" + } + ["args"]=> + array(3) { + ["a"]=> + NULL + ["b"]=> + object(stdClass)#%d (0) { + } + ["c"]=> + array(3) { + [0]=> + int(20) + [1]=> + object(stdClass)#%d (0) { + } + ["four"]=> + int(4) + } + } +} diff --git a/Zend/tests/partial_application/variation_debug_002.phpt b/Zend/tests/partial_application/variation_debug_002.phpt new file mode 100644 index 0000000000000..ef6fa8e545336 --- /dev/null +++ b/Zend/tests/partial_application/variation_debug_002.phpt @@ -0,0 +1,48 @@ +--TEST-- +Partial application variation debug internal +--FILE-- + +--EXPECTF-- +object(Closure)#%d (2) { + ["parameter"]=> + array(2) { + ["$callback"]=> + string(10) "" + ["$arrays"]=> + string(10) "" + } + ["args"]=> + array(3) { + ["callback"]=> + NULL + ["array"]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + ["arrays"]=> + array(3) { + [0]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [1]=> + NULL + ["four"]=> + object(stdClass)#%d (0) { + } + } + } +} + diff --git a/Zend/tests/partial_application/variation_ex_001.phpt b/Zend/tests/partial_application/variation_ex_001.phpt new file mode 100644 index 0000000000000..dc72ccdae797c --- /dev/null +++ b/Zend/tests/partial_application/variation_ex_001.phpt @@ -0,0 +1,14 @@ +--TEST-- +Partial application variation uaf in cleanup unfinished calls +--FILE-- + +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/variation_factory_001.phpt b/Zend/tests/partial_application/variation_factory_001.phpt new file mode 100644 index 0000000000000..52c73749bd901 --- /dev/null +++ b/Zend/tests/partial_application/variation_factory_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +Partial application variation internal object factory +--FILE-- +getTimeZone()); +?> +--EXPECTF-- +object(DateTimeZone)#%d (2) { + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(10) "Asia/Tokyo" +} + diff --git a/Zend/tests/partial_application/variation_gc_001.phpt b/Zend/tests/partial_application/variation_gc_001.phpt new file mode 100644 index 0000000000000..00b951a81ea9f --- /dev/null +++ b/Zend/tests/partial_application/variation_gc_001.phpt @@ -0,0 +1,18 @@ +--TEST-- +Partial application variation GC +--FILE-- +method = self::__construct(...); + } +} + +$foo = new Foo; +$foo->bar = $foo; + +echo "OK"; +?> +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/variation_gc_002.phpt b/Zend/tests/partial_application/variation_gc_002.phpt new file mode 100644 index 0000000000000..5f00705cf79b8 --- /dev/null +++ b/Zend/tests/partial_application/variation_gc_002.phpt @@ -0,0 +1,11 @@ +--TEST-- +Partial application variation GC +--FILE-- +prop = var_dump($obj, ?); + +echo "OK"; +?> +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/variation_gc_003.phpt b/Zend/tests/partial_application/variation_gc_003.phpt new file mode 100644 index 0000000000000..c919d488eac14 --- /dev/null +++ b/Zend/tests/partial_application/variation_gc_003.phpt @@ -0,0 +1,15 @@ +--TEST-- +Partial application variation GC +--FILE-- +prop = test(?, x: $obj); + +echo "OK"; +?> +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/variation_invoke_001.phpt b/Zend/tests/partial_application/variation_invoke_001.phpt new file mode 100644 index 0000000000000..eed2ad12b17b4 --- /dev/null +++ b/Zend/tests/partial_application/variation_invoke_001.phpt @@ -0,0 +1,23 @@ +--TEST-- +Partial application variation __invoke +--FILE-- +__invoke(32) == 42) { + echo "OK\n"; +} + +try { + $foo->nothing(); +} catch (Error $ex) { + echo "OK"; +} +?> +--EXPECT-- +OK +OK diff --git a/Zend/tests/partial_application/variation_nocall_001.phpt b/Zend/tests/partial_application/variation_nocall_001.phpt new file mode 100644 index 0000000000000..1f570bad2cfa5 --- /dev/null +++ b/Zend/tests/partial_application/variation_nocall_001.phpt @@ -0,0 +1,12 @@ +--TEST-- +Partial application variation no call args leak +--FILE-- + +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/variation_nocall_002.phpt b/Zend/tests/partial_application/variation_nocall_002.phpt new file mode 100644 index 0000000000000..35bcddc15e2a3 --- /dev/null +++ b/Zend/tests/partial_application/variation_nocall_002.phpt @@ -0,0 +1,14 @@ +--TEST-- +Partial application variation no call order of destruction +--FILE-- +method(...)(...); + +echo "OK"; +?> +--EXPECT-- +OK diff --git a/Zend/tests/partial_application/variation_parent_001.phpt b/Zend/tests/partial_application/variation_parent_001.phpt new file mode 100644 index 0000000000000..c6440a9481beb --- /dev/null +++ b/Zend/tests/partial_application/variation_parent_001.phpt @@ -0,0 +1,47 @@ +--TEST-- +Partial application variation parent +--FILE-- +method(10, ...); +$baz = $bar(20, ...); + +var_dump($baz, $baz()); +?> +--EXPECTF-- +object(Closure)#%d (3) { + ["this"]=> + object(Foo)#%d (0) { + } + ["parameter"]=> + array(1) { + ["$c"]=> + string(10) "" + } + ["args"]=> + array(3) { + ["a"]=> + int(10) + ["b"]=> + int(20) + ["c"]=> + array(1) { + [0]=> + NULL + } + } +} +object(Closure)#%d (1) { + ["this"]=> + object(Foo)#%d (0) { + } +} + diff --git a/Zend/tests/partial_application/variation_pass_001.phpt b/Zend/tests/partial_application/variation_pass_001.phpt new file mode 100644 index 0000000000000..e432e079b45dd --- /dev/null +++ b/Zend/tests/partial_application/variation_pass_001.phpt @@ -0,0 +1,14 @@ +--TEST-- +Partial application variation pass +--FILE-- +getMessage()); +} +?> +--EXPECT-- +too many arguments or placeholders for application of Foo::__construct, 1 given and a maximum of 0 expected diff --git a/Zend/tests/partial_application/variation_scope_001.phpt b/Zend/tests/partial_application/variation_scope_001.phpt new file mode 100644 index 0000000000000..afdfba9e920d0 --- /dev/null +++ b/Zend/tests/partial_application/variation_scope_001.phpt @@ -0,0 +1,18 @@ +--TEST-- +Partial application variation called scope +--FILE-- +method(...); + +$bar(); +?> +--EXPECT-- +Foo::method diff --git a/Zend/tests/partial_application/variation_strict_001.phpt b/Zend/tests/partial_application/variation_strict_001.phpt new file mode 100644 index 0000000000000..f1aebb7d2d01e --- /dev/null +++ b/Zend/tests/partial_application/variation_strict_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +Partial application variation: strict_types declared +--FILE-- +getMessage()); +} +?> +--EXPECT-- +foo(): Argument #1 ($int) must be of type int, string given + diff --git a/Zend/tests/partial_application/variation_variadics_001.phpt b/Zend/tests/partial_application/variation_variadics_001.phpt new file mode 100644 index 0000000000000..79deca98f2f9e --- /dev/null +++ b/Zend/tests/partial_application/variation_variadics_001.phpt @@ -0,0 +1,26 @@ +--TEST-- +Partial application variation variadics user +--FILE-- + +--EXPECTF-- +Function [ partial function foo ] { + @@ %s 6 - 6 + + - Parameters [1] { + Parameter #0 [ ...$b ] + } +} +int(10) +int(100) +int(1000) +int(10000) diff --git a/Zend/tests/partial_application/variation_variadics_002.phpt b/Zend/tests/partial_application/variation_variadics_002.phpt new file mode 100644 index 0000000000000..fba07a365b143 --- /dev/null +++ b/Zend/tests/partial_application/variation_variadics_002.phpt @@ -0,0 +1,19 @@ +--TEST-- +Partial application variation variadics internal +--FILE-- + +--EXPECTF-- +Function [ partial function sprintf ] { + + - Parameters [1] { + Parameter #0 [ mixed ...$values ] + } + - Return [ string ] +} +100 1000 10000 diff --git a/Zend/tests/partial_application/variation_variadics_003.phpt b/Zend/tests/partial_application/variation_variadics_003.phpt new file mode 100644 index 0000000000000..c5e41ab1aeb50 --- /dev/null +++ b/Zend/tests/partial_application/variation_variadics_003.phpt @@ -0,0 +1,50 @@ +--TEST-- +Partial application variation variadics interactions +--FILE-- +getMessage()); +} + +try { + $foo = foo(?, ?, ?); // FAIL 2 expected, 3 given +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +function bar($a, $b, ...$c) { + var_dump(func_get_args()); +} + +$bar = bar(?, ?); + +try { + $bar(1, 2, 3); // FAIL 3 given, maximum 2 expected +} catch (Error $ex) { + printf("%s\n", $ex->getMessage()); +} + +$foo = foo(?, ?, ...); + +$foo(1, 2, 3); // OK +?> +--EXPECTF-- +too many arguments for application of foo, 3 given and a maximum of 2 expected, declared in %s on line %d +too many arguments or placeholders for application of foo, 3 given and a maximum of 2 expected, declared in %s on line %d +too many arguments for application of bar, 3 given and a maximum of 2 expected, declared in %s on line %d +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} diff --git a/Zend/tests/partial_application/variation_variadics_004.phpt b/Zend/tests/partial_application/variation_variadics_004.phpt new file mode 100644 index 0000000000000..6cda0fc81f5e7 --- /dev/null +++ b/Zend/tests/partial_application/variation_variadics_004.phpt @@ -0,0 +1,65 @@ +--TEST-- +Partial application variation variadics and optional args +--FILE-- + $day, "month" => $month, "year" => $year]; +} + +$foo = foo(..., year: 2006); + +var_dump($foo(2)); + +$foo = foo(..., month: 12); + +$bar = $foo(..., year: 2016); + +var_dump($foo(2)); + +var_dump($bar(2)); + +var_dump($foo()); + +var_dump($bar()); +?> +--EXPECTF-- +array(3) { + ["day"]=> + int(2) + ["month"]=> + int(1) + ["year"]=> + int(2006) +} +array(3) { + ["day"]=> + int(2) + ["month"]=> + int(12) + ["year"]=> + int(2005) +} +array(3) { + ["day"]=> + int(2) + ["month"]=> + int(12) + ["year"]=> + int(2016) +} +array(3) { + ["day"]=> + int(1) + ["month"]=> + int(1) + ["year"]=> + int(2005) +} +array(3) { + ["day"]=> + int(1) + ["month"]=> + int(12) + ["year"]=> + int(2005) +} diff --git a/Zend/tests/partial_application/variation_variadics_006.phpt b/Zend/tests/partial_application/variation_variadics_006.phpt new file mode 100644 index 0000000000000..923bddcbe18f6 --- /dev/null +++ b/Zend/tests/partial_application/variation_variadics_006.phpt @@ -0,0 +1,18 @@ +--TEST-- +Partial application variation named may overwrite variadic placeholder +--FILE-- + +--EXPECTF-- +array(1) { + [0]=> + string(1) "a" +} + diff --git a/Zend/tests/partial_application/variation_variadics_007.phpt b/Zend/tests/partial_application/variation_variadics_007.phpt new file mode 100644 index 0000000000000..1688112787ad8 --- /dev/null +++ b/Zend/tests/partial_application/variation_variadics_007.phpt @@ -0,0 +1,14 @@ +--TEST-- +Partial application variation extra through variadic +--FILE-- + $a + $b)); +?> +--EXPECT-- +int(3) diff --git a/Zend/tests/partial_application/variation_variadics_008.phpt b/Zend/tests/partial_application/variation_variadics_008.phpt new file mode 100644 index 0000000000000..214ed9b4db9cb --- /dev/null +++ b/Zend/tests/partial_application/variation_variadics_008.phpt @@ -0,0 +1,17 @@ +--TEST-- +Partial application variation variadics wrong signature checked +--FILE-- +getMessage() . PHP_EOL; +} +?> +--EXPECT-- +too many arguments or placeholders for application of Closure::__invoke, 2 given and a maximum of 1 expected + diff --git a/Zend/zend.c b/Zend/zend.c index 63f90c4d4c215..a03ed458453d1 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -35,6 +35,7 @@ #include "zend_attributes.h" #include "zend_observer.h" #include "zend_fibers.h" +#include "zend_partial.h" #include "Optimizer/zend_optimizer.h" static size_t global_map_ptr_last = 0; @@ -1010,6 +1011,8 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ tsrm_set_new_thread_end_handler(zend_new_thread_end_handler); tsrm_set_shutdown_handler(zend_interned_strings_dtor); #endif + + zend_partial_startup(); } /* }}} */ diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index e222e4bd74019..337c362c471fe 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1728,6 +1728,13 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio EMPTY_SWITCH_DEFAULT_CASE(); } break; + case ZEND_AST_PLACEHOLDER_ARG: + if (ast->attr == _IS_PLACEHOLDER_ARG) { + APPEND_STR("?"); + } else if (ast->attr == _IS_PLACEHOLDER_VARIADIC) { + APPEND_STR("..."); + } + break; /* 1 child node */ case ZEND_AST_VAR: diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 0e3468ebde110..3fadd27c02999 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -70,6 +70,7 @@ enum _zend_ast_kind { ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_TYPE, ZEND_AST_CONSTANT_CLASS, + ZEND_AST_PLACEHOLDER_ARG, /* 1 child node */ ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT, diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 5ae122b7f94ab..6b8df76e92517 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -25,6 +25,7 @@ #include "zend_interfaces.h" #include "zend_objects.h" #include "zend_objects_API.h" +#include "zend_partial.h" #include "zend_globals.h" #include "zend_closures_arginfo.h" @@ -40,6 +41,8 @@ typedef struct _zend_closure { ZEND_API zend_class_entry *zend_ce_closure; static zend_object_handlers closure_handlers; +static zval zend_closure_no_this; + ZEND_METHOD(Closure, __invoke) /* {{{ */ { zend_function *func = EX(func); @@ -55,9 +58,11 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */ RETVAL_FALSE; } - /* destruct the function also, then - we have allocated it in get_method */ - zend_string_release_ex(func->internal_function.function_name, 0); - efree(func); + if (!(func->common.fn_flags & ZEND_ACC_TRAMPOLINE_PERMANENT)) { + /* destruct the function also, then - we have allocated it in get_method */ + zend_string_release_ex(func->internal_function.function_name, 0); + efree(func); + } #if ZEND_DEBUG execute_data->func = NULL; #endif @@ -69,6 +74,7 @@ static bool zend_valid_closure_binding( { zend_function *func = &closure->func; bool is_fake_closure = (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) != 0; + if (newthis) { if (func->common.fn_flags & ZEND_ACC_STATIC) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); @@ -142,7 +148,13 @@ ZEND_METHOD(Closure, call) return; } - if (closure->func.common.fn_flags & ZEND_ACC_GENERATOR) { + if (closure->func.common.fn_flags & ZEND_ACC_PARTIAL) { + zval new_closure; + zend_partial_bind(&new_closure, ZEND_THIS, newthis, newclass); + closure = (zend_closure *) Z_OBJ(new_closure); + fci_cache.function_handler = zend_partial_get_trampoline(Z_OBJ(new_closure)); + newobj = Z_OBJ(new_closure); + } else if (closure->func.common.fn_flags & ZEND_ACC_GENERATOR) { zval new_closure; zend_create_closure(&new_closure, &closure->func, newclass, closure->called_scope, newthis); closure = (zend_closure *) Z_OBJ(new_closure); @@ -183,7 +195,9 @@ ZEND_METHOD(Closure, call) ZVAL_COPY_VALUE(return_value, &closure_result); } - if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { + if (!fci_cache.function_handler) { + OBJ_RELEASE(newobj); + } else if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { /* copied upon generator creation */ GC_DELREF(&closure->std); } else if (ZEND_USER_CODE(my_function.type) @@ -221,7 +235,11 @@ static void do_closure_bind(zval *return_value, zval *zclosure, zval *newthis, z called_scope = ce; } - zend_create_closure(return_value, &closure->func, ce, called_scope, newthis); + if (closure->func.common.fn_flags & ZEND_ACC_PARTIAL) { + zend_partial_bind(return_value, zclosure, newthis, called_scope); + } else { + zend_create_closure(return_value, &closure->func, ce, called_scope, newthis); + } } /* {{{ Create a closure from another one and bind to another object and scope */ @@ -423,6 +441,12 @@ ZEND_API const zend_function *zend_get_closure_method_def(zend_object *obj) /* { ZEND_API zval* zend_get_closure_this_ptr(zval *obj) /* {{{ */ { zend_closure *closure = (zend_closure *)Z_OBJ_P(obj); + + if (UNEXPECTED(Z_TYPE(closure->this_ptr) != IS_OBJECT)) { + /* zend_partial This may refer to a type */ + return &zend_closure_no_this; + } + return &closure->this_ptr; } /* }}} */ @@ -501,7 +525,7 @@ int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_f /* }}} */ /* *is_temp is int due to Object Handler API */ -static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ +HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { zend_closure *closure = (zend_closure *)object; zval val; @@ -542,7 +566,7 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) } } - if (Z_TYPE(closure->this_ptr) != IS_UNDEF) { + if (Z_TYPE(closure->this_ptr) == IS_OBJECT) { Z_ADDREF(closure->this_ptr); zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_THIS), &closure->this_ptr); } @@ -624,6 +648,8 @@ void zend_register_closure_ce(void) /* {{{ */ closure_handlers.get_debug_info = zend_closure_get_debug_info; closure_handlers.get_closure = zend_closure_get_closure; closure_handlers.get_gc = zend_closure_get_gc; + + ZVAL_UNDEF(&zend_closure_no_this); } /* }}} */ diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h index 5b990cc0f9b60..f66b095fbc95f 100644 --- a/Zend/zend_closures.h +++ b/Zend/zend_closures.h @@ -29,6 +29,7 @@ BEGIN_EXTERN_C() void zend_register_closure_ce(void); void zend_closure_bind_var(zval *closure_zv, zend_string *var_name, zval *var); void zend_closure_bind_var_ex(zval *closure_zv, uint32_t offset, zval *val); +HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp); extern ZEND_API zend_class_entry *zend_ce_closure; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index dade906f4b891..428c2da64c50e 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3445,11 +3445,12 @@ static uint32_t zend_get_arg_num(zend_function *fn, zend_string *arg_name) { } uint32_t zend_compile_args( - zend_ast *ast, zend_function *fbc, bool *may_have_extra_named_args) /* {{{ */ + zend_ast *ast, zend_function *fbc, bool *may_have_extra_named_args, bool *is_call_partial) /* {{{ */ { zend_ast_list *args = zend_ast_get_list(ast); uint32_t i; bool uses_arg_unpack = 0; + bool uses_variadic_placeholder = 0; uint32_t arg_count = 0; /* number of arguments not including unpacks */ /* Whether named arguments are used syntactically, to enforce language level limitations. @@ -3459,6 +3460,8 @@ uint32_t zend_compile_args( bool may_have_undef = 0; /* Whether there may be any extra named arguments collected into a variadic. */ *may_have_extra_named_args = 0; + /* Whether this is a partial call */ + *is_call_partial = false; for (i = 0; i < args->children; ++i) { zend_ast *arg = args->child[i]; @@ -3475,6 +3478,11 @@ uint32_t zend_compile_args( "Cannot use argument unpacking after named arguments"); } + if (*is_call_partial) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot combine partial application and unpacking"); + } + uses_arg_unpack = 1; fbc = NULL; @@ -3491,6 +3499,47 @@ uint32_t zend_compile_args( continue; } + if (arg->kind == ZEND_AST_PLACEHOLDER_ARG) { + if (uses_arg_unpack) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot combine partial application and unpacking"); + } + + if (arg->attr == _IS_PLACEHOLDER_VARIADIC) { + if (uses_named_args) { + zend_error_noreturn(E_COMPILE_ERROR, + "Named arguments must come after all placeholders"); + } + + if (uses_variadic_placeholder) { + zend_error_noreturn(E_COMPILE_ERROR, + "Variadic placeholder may only appear once"); + } + + uses_variadic_placeholder = true; + } else if (arg->attr == _IS_PLACEHOLDER_ARG) { + if (uses_named_args) { + zend_error_noreturn(E_COMPILE_ERROR, + "Named arguments must come after all placeholders"); + } + + if (uses_variadic_placeholder) { + zend_error_noreturn(E_COMPILE_ERROR, + "Only named arguments may follow variadic placeholder"); + } + } + + fbc = NULL; + + opline = zend_emit_op(NULL, ZEND_SEND_PLACEHOLDER, NULL, NULL); + opline->op1.num = arg->attr; + opline->op2.num = arg_num; + + *is_call_partial = true; + arg_count++; + continue; + } + if (arg->kind == ZEND_AST_NAMED_ARG) { uses_named_args = 1; arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0])); @@ -3525,6 +3574,11 @@ uint32_t zend_compile_args( "Cannot use positional argument after named argument"); } + if (uses_variadic_placeholder) { + zend_error_noreturn(E_COMPILE_ERROR, + "Only named arguments may follow variadic placeholder"); + } + arg_count++; } @@ -3635,8 +3689,12 @@ uint32_t zend_compile_args( } } - if (may_have_undef) { - zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL); + if (!*is_call_partial) { + if (may_have_undef) { + zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL); + } + } else { + zend_emit_op(NULL, ZEND_CHECK_PARTIAL_ARGS, NULL, NULL); } return arg_count; @@ -3669,14 +3727,40 @@ ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc) } /* }}} */ +void zend_compile_call_partial(znode *result, uint32_t arg_count, bool may_have_extra_named_args, uint32_t opnum_init, zend_function *fbc) { /* {{{ */ + zend_op *opline = &CG(active_op_array)->opcodes[opnum_init]; + znode op1; + + opline->extended_value = arg_count; + + if (opline->opcode == ZEND_INIT_FCALL) { + opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc); + } else if (opline->opcode == ZEND_NEW) { + GET_NODE(&op1, opline->result); + } + + opline = zend_emit_op(result, ZEND_DO_FCALL_PARTIAL, + (opline->opcode == ZEND_NEW) ? &op1 : NULL, NULL); + + if (may_have_extra_named_args) { + opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS; + } +} /* }}} */ + void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */ { zend_op *opline; uint32_t opnum_init = get_next_op_number() - 1; uint32_t arg_count; bool may_have_extra_named_args; + bool is_partial_call; + + arg_count = zend_compile_args(args_ast, fbc, &may_have_extra_named_args, &is_partial_call); - arg_count = zend_compile_args(args_ast, fbc, &may_have_extra_named_args); + if (is_partial_call) { + zend_compile_call_partial(result, arg_count, may_have_extra_named_args, opnum_init, fbc); + return; + } zend_do_extended_fcall_begin(); @@ -3691,6 +3775,7 @@ void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function * if (may_have_extra_named_args) { opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS; } + zend_do_extended_fcall_end(); } /* }}} */ @@ -3755,12 +3840,14 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a } /* }}} */ -static inline bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ */ +static inline bool zend_args_contain_unpack_or_named_or_partial(zend_ast_list *args) /* {{{ */ { uint32_t i; for (i = 0; i < args->children; ++i) { zend_ast *arg = args->child[i]; - if (arg->kind == ZEND_AST_UNPACK || arg->kind == ZEND_AST_NAMED_ARG) { + if (arg->kind == ZEND_AST_UNPACK || + arg->kind == ZEND_AST_NAMED_ARG || + arg->kind == ZEND_AST_PLACEHOLDER_ARG) { return 1; } } @@ -3987,7 +4074,7 @@ zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_stri zend_string *name = zend_resolve_function_name(orig_name, args->child[1]->child[0]->attr, &is_fully_qualified); if (zend_string_equals_literal_ci(name, "array_slice") - && !zend_args_contain_unpack_or_named(list) + && !zend_args_contain_unpack_or_named_or_partial(list) && list->children == 3 && list->child[1]->kind == ZEND_AST_ZVAL) { zval *zv = zend_ast_get_zval(list->child[1]); @@ -4323,7 +4410,7 @@ zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, ze return FAILURE; } - if (zend_args_contain_unpack_or_named(args)) { + if (zend_args_contain_unpack_or_named_or_partial(args)) { return FAILURE; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 76405a3689dc9..29a99c090cd84 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -238,7 +238,7 @@ typedef struct _zend_oparray_context { /* or IS_CONSTANT_VISITED_MARK | | | */ #define ZEND_CLASS_CONST_IS_CASE (1 << 6) /* | | | X */ /* | | | */ -/* Class Flags (unused: 29...) | | | */ +/* Class Flags (unused: 30...) | | | */ /* =========== | | | */ /* | | | */ /* Special class types | | | */ @@ -301,7 +301,7 @@ typedef struct _zend_oparray_context { /* loaded from file cache to process memory | | | */ #define ZEND_ACC_FILE_CACHED (1 << 27) /* X | | | */ /* | | | */ -/* Function Flags (unused: 27-30) | | | */ +/* Function Flags (unused: 29-30) | | | */ /* ============== | | | */ /* | | | */ /* deprecation flag | | | */ @@ -357,6 +357,12 @@ typedef struct _zend_oparray_context { /* method flag used by Closure::__invoke() (int only) | | | */ #define ZEND_ACC_USER_ARG_INFO (1 << 26) /* | X | | */ /* | | | */ +/* flag used by partial application (int only) | | | */ +#define ZEND_ACC_PARTIAL (1 << 27) /* | X | | */ +/* | | | */ +/* trampoline is permanent | | | */ +#define ZEND_ACC_TRAMPOLINE_PERMANENT (1 << 28) /* | X | | */ +/* | | | */ /* op_array uses strict mode types | | | */ #define ZEND_ACC_STRICT_TYPES (1U << 31) /* | X | | */ @@ -555,6 +561,7 @@ struct _zend_execute_data { #define ZEND_CALL_OBSERVED (1 << 28) /* "fcall_begin" observer handler may set this flag */ /* to prevent optimization in RETURN handler and */ /* keep all local variables for "fcall_end" handler */ +#define ZEND_CALL_VARIADIC_PLACEHOLDER (1<<29) #define ZEND_CALL_SEND_ARG_BY_REF (1u << 31) #define ZEND_CALL_NESTED_FUNCTION (ZEND_CALL_FUNCTION | ZEND_CALL_NESTED) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 748967cf5e5d2..96814d4320256 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -34,6 +34,7 @@ #include "zend_exceptions.h" #include "zend_interfaces.h" #include "zend_closures.h" +#include "zend_partial.h" #include "zend_generators.h" #include "zend_vm.h" #include "zend_dtrace.h" @@ -1157,8 +1158,9 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ * trust that arginfo matches what is enforced by zend_parse_parameters. */ static zend_always_inline bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_data *call) { - if (fbc->internal_function.handler == ZEND_FN(pass)) { - /* Be lenient about the special pass function. */ + if (fbc->internal_function.handler == ZEND_FN(pass) || + fbc->internal_function.handler == zend_partial_call_magic) { + /* Be lenient about the special pass functions. */ return 0; } @@ -3833,6 +3835,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: + case ZEND_DO_FCALL_PARTIAL: level++; break; case ZEND_INIT_FCALL: @@ -3869,6 +3872,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o case ZEND_SEND_ARRAY: case ZEND_SEND_UNPACK: case ZEND_CHECK_UNDEF_ARGS: + case ZEND_CHECK_PARTIAL_ARGS: if (level == 0) { do_exit = 1; } @@ -3888,6 +3892,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: + case ZEND_DO_FCALL_PARTIAL: level++; break; case ZEND_INIT_FCALL: @@ -3910,9 +3915,6 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o zend_vm_stack_free_args(EX(call)); - if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { - OBJ_RELEASE(Z_OBJ(call->This)); - } if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { zend_free_extra_named_params(call->extra_named_params); } @@ -3922,6 +3924,9 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o zend_string_release_ex(call->func->common.function_name, 0); zend_free_trampoline(call->func); } + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { + OBJ_RELEASE(Z_OBJ(call->This)); + } EX(call) = call->prev_execute_data; zend_vm_stack_free_call_frame(call); @@ -4477,8 +4482,8 @@ zval * ZEND_FASTCALL zend_handle_named_arg( arg = zend_hash_add_empty_element(call->extra_named_params, arg_name); if (!arg) { - zend_throw_error(NULL, "Named parameter $%s overwrites previous argument", - ZSTR_VAL(arg_name)); + zend_throw_error(NULL, "Named parameter $%s overwrites previous %s", + ZSTR_VAL(arg_name), Z_TYPE_P(arg) == _IS_PLACEHOLDER_ARG ? "placeholder" : "argument"); return NULL; } *arg_num_ptr = arg_offset + 1; @@ -4507,9 +4512,14 @@ zval * ZEND_FASTCALL zend_handle_named_arg( } } else { arg = ZEND_CALL_VAR_NUM(call, arg_offset); + + if (UNEXPECTED(Z_TYPE_P(arg) == _IS_PLACEHOLDER_VARIADIC)) { + ZVAL_UNDEF(arg); + } + if (UNEXPECTED(!Z_ISUNDEF_P(arg))) { - zend_throw_error(NULL, "Named parameter $%s overwrites previous argument", - ZSTR_VAL(arg_name)); + zend_throw_error(NULL, "Named parameter $%s overwrites previous %s", + ZSTR_VAL(arg_name), Z_TYPE_P(arg) == _IS_PLACEHOLDER_ARG ? "placeholder" : "argument"); return NULL; } } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index e783a7d9aa1e7..73fdd14ce451a 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -840,6 +840,8 @@ argument: expr { $$ = $1; } | identifier ':' expr { $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, $3); } + | '?' { $$ = zend_ast_create_ex(ZEND_AST_PLACEHOLDER_ARG, _IS_PLACEHOLDER_ARG); } + | T_ELLIPSIS { $$ = zend_ast_create_ex(ZEND_AST_PLACEHOLDER_ARG, _IS_PLACEHOLDER_VARIADIC); } | T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); } ; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index fdbab21a9bec7..dee5557343d54 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -35,6 +35,8 @@ #define ZEND_WRONG_PROPERTY_OFFSET 0 +static zend_arg_info zend_call_trampoline_arginfo[1] = {{0}}; + /* guard flags */ #define IN_GET (1<<0) #define IN_SET (1<<1) @@ -1125,6 +1127,13 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) } /* }}} */ +static zend_always_inline zend_arg_info* zend_get_call_trampoline_arginfo() { + if (UNEXPECTED(zend_call_trampoline_arginfo[0].name == NULL)) { + zend_call_trampoline_arginfo[0].name = ZSTR_KNOWN(ZEND_STR_ARGS); + } + return zend_call_trampoline_arginfo; +} + ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend_string *method_name, int is_static) /* {{{ */ { size_t mname_len; @@ -1134,7 +1143,6 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend * The low bit must be zero, to not be interpreted as a MAP_PTR offset. */ static const void *dummy = (void*)(intptr_t)2; - static const zend_arg_info arg_info[1] = {{0}}; ZEND_ASSERT(fbc); @@ -1172,7 +1180,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend func->prototype = NULL; func->num_args = 0; func->required_num_args = 0; - func->arg_info = (zend_arg_info *) arg_info; + func->arg_info = zend_get_call_trampoline_arginfo(); return (zend_function*)func; } diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 53eef829282ce..d680eadff5620 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -256,7 +256,7 @@ ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose #define zend_free_trampoline(func) do { \ if ((func) == &EG(trampoline)) { \ EG(trampoline).common.function_name = NULL; \ - } else { \ + } else if (!(func->common.fn_flags & ZEND_ACC_TRAMPOLINE_PERMANENT)) { \ efree(func); \ } \ } while (0) diff --git a/Zend/zend_partial.c b/Zend/zend_partial.c new file mode 100644 index 0000000000000..55da8c5f82f75 --- /dev/null +++ b/Zend/zend_partial.c @@ -0,0 +1,939 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: krakjoe | + +----------------------------------------------------------------------+ +*/ +#include "zend.h" +#include "zend_API.h" +#include "zend_interfaces.h" +#include "zend_closures.h" +#include "zend_partial.h" + +typedef struct _zend_partial { + zend_object std; + /* this is the prototype generated from application */ + zend_function prototype; + zval This; + /* this is the unmodified function that will be invoked at call time */ + zend_function func; + /* this will be returned by get_closure, and has arginfo of prototype + and will invoke func */ + zend_function trampoline; + uint32_t argc; + zval *argv; + zend_array *named; +} zend_partial; + +static zend_object_handlers zend_partial_handlers; + +static zend_arg_info zend_call_magic_arginfo[1]; + +#define Z_IS_PLACEHOLDER_ARG_P(p) \ + (Z_TYPE_P(p) == _IS_PLACEHOLDER_ARG) + +#define Z_IS_PLACEHOLDER_VARIADIC_P(p) \ + (Z_TYPE_P(p) == _IS_PLACEHOLDER_VARIADIC) + +#define Z_IS_PLACEHOLDER_P(p) \ + (Z_IS_PLACEHOLDER_ARG_P(p) || Z_IS_PLACEHOLDER_VARIADIC_P(p)) + +#define Z_IS_NOT_PLACEHOLDER_P(p) \ + (!Z_IS_PLACEHOLDER_ARG_P(p) && !Z_IS_PLACEHOLDER_VARIADIC_P(p)) + +#define ZEND_PARTIAL_IS_CALL_TRAMPOLINE(func) \ + UNEXPECTED(((func)->type == ZEND_USER_FUNCTION) && ((func)->op_array.opcodes == &EG(call_trampoline_op))) + +#define ZEND_PARTIAL_FUNC_SIZE(func) \ + (((func)->type == ZEND_INTERNAL_FUNCTION) ? sizeof(zend_internal_function) : sizeof(zend_op_array)) + +#define ZEND_PARTIAL_FUNC_FLAG(func, flags) \ + ((func)->common.fn_flags & flags) + +#define ZEND_PARTIAL_FUNC_DEL(func, flag) \ + ((func)->common.fn_flags &= ~flag) + +#define ZEND_PARTIAL_FUNC_ADD(func, flag) \ + ((func)->common.fn_flags |= flag) + +#define ZEND_PARTIAL_CALL_FLAG(partial, flag) \ + (ZEND_CALL_INFO(partial) & flag) + +static zend_always_inline uint32_t zend_partial_signature_size(zend_partial *partial) { + uint32_t count = MAX(partial->func.common.num_args, partial->argc); + + if (ZEND_PARTIAL_FUNC_FLAG(&partial->func, ZEND_ACC_HAS_RETURN_TYPE)) { + count++; + } + + if (ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_VARIADIC)|| + ZEND_PARTIAL_FUNC_FLAG(&partial->func, ZEND_ACC_VARIADIC)) { + count++; + } + + return count * sizeof(zend_arg_info); +} + +static zend_always_inline zend_function* zend_partial_signature_create(zend_partial *partial, zend_function *prototype) { + zend_arg_info *signature = emalloc(zend_partial_signature_size(partial)), *info = signature; + + memcpy(&partial->prototype, prototype, ZEND_PARTIAL_FUNC_SIZE(prototype)); + + if (ZEND_PARTIAL_FUNC_FLAG(prototype, ZEND_ACC_HAS_RETURN_TYPE)) { + memcpy(info, + prototype->common.arg_info - 1, sizeof(zend_arg_info)); + info++; + } + + uint32_t offset = 0, num = 0, required = 0, limit = partial->argc; + + ZEND_PARTIAL_FUNC_DEL(&partial->prototype, ZEND_ACC_VARIADIC); + + while (offset < limit) { + zval *arg = &partial->argv[offset]; + + if (Z_IS_PLACEHOLDER_ARG_P(arg)) { + if (offset < prototype->common.num_args) { + num++; + required++; + memcpy(info, + &prototype->common.arg_info[offset], + sizeof(zend_arg_info)); + ZEND_TYPE_FULL_MASK(info->type) &= ~_ZEND_IS_VARIADIC_BIT; + info++; + } else if (ZEND_PARTIAL_FUNC_FLAG(prototype, ZEND_ACC_VARIADIC)) { + num++; + required++; + if (ZEND_PARTIAL_IS_CALL_TRAMPOLINE(prototype)) { + memcpy(info, zend_call_magic_arginfo, sizeof(zend_arg_info)); + } else { + memcpy(info, + prototype->common.arg_info + prototype->common.num_args, + sizeof(zend_arg_info)); + } + + ZEND_TYPE_FULL_MASK(info->type) &= ~_ZEND_IS_VARIADIC_BIT; + info++; + } else { + ZEND_ASSERT(0); + } + } else if (Z_IS_PLACEHOLDER_VARIADIC_P(arg) || Z_ISUNDEF_P(arg)) { + if (offset < partial->func.common.num_args) { + while (offset < partial->func.common.num_args) { + if ((offset < partial->argc) && + !Z_IS_PLACEHOLDER_P(&partial->argv[offset]) && + !Z_ISUNDEF(partial->argv[offset])) { + offset++; + continue; + } + + num++; + memcpy(info, + &partial->func.common.arg_info[offset], + sizeof(zend_arg_info)); + ZEND_TYPE_FULL_MASK(info->type) &= ~_ZEND_IS_VARIADIC_BIT; + info++; + offset++; + } + + if (ZEND_PARTIAL_FUNC_FLAG(prototype, ZEND_ACC_VARIADIC)) { + ZEND_ASSERT(!ZEND_PARTIAL_IS_CALL_TRAMPOLINE(prototype)); + memcpy(info, + prototype->common.arg_info + prototype->common.num_args, + sizeof(zend_arg_info)); + + if (ZEND_TYPE_FULL_MASK(info->type) & _ZEND_IS_VARIADIC_BIT) { + ZEND_PARTIAL_FUNC_ADD(&partial->prototype, ZEND_ACC_VARIADIC); + } + num++; + } + break; + } else if (ZEND_PARTIAL_FUNC_FLAG(prototype, ZEND_ACC_VARIADIC)) { + ZEND_PARTIAL_FUNC_ADD(&partial->prototype, ZEND_ACC_VARIADIC); + num++; + if (ZEND_PARTIAL_IS_CALL_TRAMPOLINE(prototype)) { + memcpy(info, zend_call_magic_arginfo, sizeof(zend_arg_info)); + } else { + memcpy(info, + prototype->common.arg_info + prototype->common.num_args, + sizeof(zend_arg_info)); + } + info++; + break; + } + } + + offset++; + } + + if (ZEND_PARTIAL_FUNC_FLAG(&partial->prototype, ZEND_ACC_VARIADIC)) { + num--; + } + + partial->prototype.common.num_args = num; + partial->prototype.common.required_num_args = required; + partial->prototype.common.arg_info = signature; + + if (ZEND_PARTIAL_FUNC_FLAG(&partial->prototype, ZEND_ACC_HAS_RETURN_TYPE)) { + partial->prototype.common.arg_info++; + } + + ZEND_PARTIAL_FUNC_ADD(&partial->prototype, ZEND_ACC_PARTIAL); + + partial->prototype.common.prototype = &partial->func; + + if (prototype->type == ZEND_INTERNAL_FUNCTION) { + return &partial->prototype; + } + + zend_string *filename = zend_get_executed_filename_ex(); + + if (!filename) { + if (partial->prototype.op_array.filename) { + zend_string_addref(partial->prototype.op_array.filename); + } + return &partial->prototype; + } + + partial->prototype.op_array.filename = zend_string_copy(filename); + partial->prototype.op_array.line_start = + partial->prototype.op_array.line_end = zend_get_executed_lineno(); + + return &partial->prototype; +} + +static zend_always_inline zend_partial* zend_partial_fetch(zval *This) { + if (!This || Z_TYPE_P(This) != IS_OBJECT) { + return NULL; + } + + if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(This), zend_ce_closure))) { + return NULL; + } + + zend_partial *ptr = (zend_partial*) Z_OBJ_P(This); + + if (!ZEND_PARTIAL_FUNC_FLAG(&ptr->prototype, ZEND_ACC_PARTIAL)) { + return NULL; + } + + return ptr; +} + +static zend_always_inline void zend_partial_trampoline_create(zend_partial *partial, zend_function *trampoline) +{ + const uint32_t keep_flags = + ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_VARIADIC | ZEND_ACC_HAS_RETURN_TYPE | ZEND_ACC_STRICT_TYPES; + + trampoline->common = partial->prototype.common; + trampoline->type = ZEND_INTERNAL_FUNCTION; + trampoline->internal_function.fn_flags = + ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | ZEND_ACC_PARTIAL | ZEND_ACC_TRAMPOLINE_PERMANENT | (partial->prototype.common.fn_flags & keep_flags); + if (partial->func.type != ZEND_INTERNAL_FUNCTION || (partial->func.common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { + trampoline->internal_function.fn_flags |= + ZEND_ACC_USER_ARG_INFO; + } + trampoline->internal_function.handler = zend_partial_call_magic; + trampoline->internal_function.module = 0; + trampoline->internal_function.scope = zend_ce_closure; + trampoline->internal_function.function_name = ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE); +} + +static zend_always_inline zend_object* zend_partial_new(zend_class_entry *type, uint32_t info) { + zend_partial *partial = ecalloc(1, sizeof(zend_partial)); + + zend_object_std_init(&partial->std, type); + + partial->std.handlers = &zend_partial_handlers; + + ZEND_ADD_CALL_FLAG(partial, info); + + return (zend_object*) partial; +} + +static zend_always_inline void zend_partial_debug_add(zend_function *function, HashTable *ht, zend_arg_info *info, zval *value) { + if (function->type == ZEND_USER_FUNCTION || ZEND_PARTIAL_FUNC_FLAG(function, ZEND_ACC_USER_ARG_INFO)) { + zend_hash_add_new(ht, info->name, value); + } else { + zend_internal_arg_info *internal = (zend_internal_arg_info*) info; + + zend_hash_str_add_new(ht, internal->name, strlen(internal->name), value); + } +} + +static zend_always_inline void zend_partial_debug_fill(zend_partial *partial, HashTable *ht) { + zval *arg = partial->argv; + zval *aend = arg + partial->argc; + + zend_arg_info *info = partial->func.common.arg_info; + zend_arg_info *iend = info + partial->func.common.num_args; + + while (info < iend) { + zval param; + + ZVAL_NULL(¶m); + + if (arg < aend) { + if (Z_IS_NOT_PLACEHOLDER_P(arg)) { + ZVAL_COPY(¶m, arg); + } + arg++; + } + + zend_partial_debug_add(&partial->func, ht, info, ¶m); + + info++; + } + + if (ZEND_PARTIAL_FUNC_FLAG(&partial->func, ZEND_ACC_VARIADIC)) { + zval variadics; + + array_init(&variadics); + + zend_partial_debug_add(&partial->func, ht, info, &variadics); + + while (arg < aend) { + zval param; + + ZVAL_NULL(¶m); + + if (Z_IS_NOT_PLACEHOLDER_P(arg)) { + ZVAL_COPY(¶m, arg); + } + + zend_hash_next_index_insert(Z_ARRVAL(variadics), ¶m); + arg++; + } + + if (partial->named) { + zend_hash_merge(Z_ARRVAL(variadics), partial->named, zval_copy_ctor, true); + } + } +} + +static HashTable *zend_partial_debug(zend_object *object, int *is_temp) { + zend_partial *partial = (zend_partial*) object; + zval args; + HashTable *ht; + + ht = zend_closure_get_debug_info(object, is_temp); + + array_init(&args); + zend_hash_update(ht, ZSTR_KNOWN(ZEND_STR_ARGS), &args); + + zend_partial_debug_fill(partial, Z_ARRVAL(args)); + + return ht; +} + +static HashTable *zend_partial_get_gc(zend_object *obj, zval **table, int *n) +{ + zend_partial *partial = (zend_partial *)obj; + + if (!partial->argc && !partial->named) { + *table = Z_TYPE(partial->This) == IS_OBJECT ? &partial->This : NULL; + *n = Z_TYPE(partial->This) == IS_OBJECT ? 1 : 0; + } else { + zend_get_gc_buffer *buffer = zend_get_gc_buffer_create(); + + if (Z_TYPE(partial->This) == IS_OBJECT) { + zend_get_gc_buffer_add_zval(buffer, &partial->This); + } + + for (uint32_t arg = 0; arg < partial->argc; arg++) { + zend_get_gc_buffer_add_zval(buffer, &partial->argv[arg]); + } + + if (partial->named) { + zval named; + + ZVAL_ARR(&named, partial->named); + + zend_get_gc_buffer_add_zval(buffer, &named); + } + + zend_get_gc_buffer_use(buffer, table, n); + } + + return NULL; +} + +static zend_function *zend_partial_get_method(zend_object **object, zend_string *method, const zval *key) /* {{{ */ +{ + if (zend_string_equals_literal_ci(method, ZEND_INVOKE_FUNC_NAME)) { + zend_partial *partial = (zend_partial*) *object; + + return &partial->trampoline; + } + + return zend_std_get_method(object, method, key); +} +/* }}} */ + +static int zend_partial_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) +{ + zend_partial *partial = (zend_partial*) obj; + + *fptr_ptr = &partial->trampoline; + *obj_ptr = (zend_object*) &partial->std; + *ce_ptr = Z_TYPE(partial->This) == IS_OBJECT ? Z_OBJCE(partial->This) : NULL; + + return SUCCESS; +} + +zend_function *zend_partial_get_trampoline(zend_object *obj) { + zend_partial *partial = (zend_partial*) obj; + + return &partial->trampoline; +} + +static void zend_partial_free(zend_object *object) { + zend_partial *partial = (zend_partial*) object; + + zval *arg = partial->argv, + *end = arg + partial->argc; + + while (arg < end) { + if (Z_OPT_REFCOUNTED_P(arg)) { + zval_ptr_dtor(arg); + } + arg++; + } + + efree(partial->argv); + + if (partial->named) { + zend_array_release(partial->named); + } + + zend_arg_info *info = partial->prototype.common.arg_info; + + if (ZEND_PARTIAL_FUNC_FLAG(&partial->func, ZEND_ACC_HAS_RETURN_TYPE)) { + info--; + } + + efree(info); + + if (partial->func.type == ZEND_USER_FUNCTION) { + if (partial->prototype.op_array.filename) { + zend_string_release(partial->prototype.op_array.filename); + } + destroy_zend_function(&partial->func); + } + + if (Z_TYPE(partial->This) == IS_OBJECT) { + zval_ptr_dtor(&partial->This); + } + + zend_object_std_dtor(object); +} + +void zend_partial_startup(void) { + memcpy(&zend_partial_handlers, + &std_object_handlers, sizeof(zend_object_handlers)); + + zend_partial_handlers.free_obj = zend_partial_free; + zend_partial_handlers.get_debug_info = zend_partial_debug; + zend_partial_handlers.get_gc = zend_partial_get_gc; + zend_partial_handlers.get_closure = zend_partial_get_closure; + zend_partial_handlers.get_method = zend_partial_get_method; + + memset(&zend_call_magic_arginfo, 0, sizeof(zend_arg_info) * 1); + + zend_call_magic_arginfo[0].name = ZSTR_KNOWN(ZEND_STR_ARGS); + zend_call_magic_arginfo[0].type = (zend_type) ZEND_TYPE_INIT_NONE(_ZEND_IS_VARIADIC_BIT); +} + +static zend_always_inline zend_string* zend_partial_function_name(zend_function *function) { + if (function->type == ZEND_INTERNAL_FUNCTION) { + if (function->internal_function.handler == zend_pass_function.handler) { + return zend_string_init("__construct", sizeof("__construct")-1, 0); + } + } + return zend_string_copy(function->common.function_name); +} + +static zend_always_inline zend_string* zend_partial_scope_name(zend_execute_data *execute_data, zend_function *function) { + if (function->type == ZEND_INTERNAL_FUNCTION) { + if (function->internal_function.handler == zend_pass_function.handler) { + if (Z_OBJ(EX(This))) { + return Z_OBJCE(EX(This))->name; + } + } + } + + if (function->common.scope) { + return function->common.scope->name; + } + + return NULL; +} + +static zend_always_inline zend_string* zend_partial_symbol_name(zend_execute_data *call, zend_function *function) { + zend_string *name = zend_partial_function_name(function), + *scope = zend_partial_scope_name(call, function), + *symbol; + + if (scope) { + symbol = zend_create_member_string(scope, name); + } else { + symbol = zend_string_copy(name); + } + + zend_string_release(name); + return symbol; +} + +static zend_always_inline void zend_partial_prototype_underflow(zend_function *function, zend_string *symbol, uint32_t args, uint32_t expected, bool variadic) { + char *limit = variadic ? "at least" : "exactly"; + + if (function->type == ZEND_USER_FUNCTION) { + zend_throw_error(NULL, + "not enough arguments for application of %s, " + "%d given and %s %d expected, declared in %s on line %d", + ZSTR_VAL(symbol), args, limit, expected, + ZSTR_VAL(function->op_array.filename), function->op_array.line_start); + } else { + zend_throw_error(NULL, + "not enough arguments for application of %s, %d given and %s %d expected", + ZSTR_VAL(symbol), args, limit, expected); + } +} + +static zend_always_inline void zend_partial_prototype_overflow(zend_function *function, zend_string *symbol, uint32_t args, uint32_t expected) { + if (function->type == ZEND_USER_FUNCTION) { + zend_throw_error(NULL, + "too many arguments for application of %s, " + "%d given and a maximum of %d expected, declared in %s on line %d", + ZSTR_VAL(symbol), args, expected, + ZSTR_VAL(function->op_array.filename), function->op_array.line_start); + } else { + zend_throw_error(NULL, + "too many arguments for application of %s, %d given and a maximum of %d expected", + ZSTR_VAL(symbol), args, expected); + } +} + +static zend_always_inline void zend_partial_args_underflow(zend_function *function, zend_string *symbol, uint32_t args, uint32_t expected, bool calling, bool prototype) { + const char *what = calling ? + "arguments" : "arguments or placeholders"; + const char *from = prototype ? + "application" : "implementation"; + const char *limit = function->common.num_args <= function->common.required_num_args ? + "exactly" : "at least"; + + if (function->type == ZEND_USER_FUNCTION) { + zend_throw_error(NULL, + "not enough %s for %s of %s, " + "%d given and %s %d expected, declared in %s on line %d", + what, from, ZSTR_VAL(symbol), args, limit, expected, + ZSTR_VAL(function->op_array.filename), function->op_array.line_start); + } else { + zend_throw_error(NULL, + "not enough %s for %s of %s, %d given and %s %d expected", + what, from, ZSTR_VAL(symbol), args, limit, expected); + } +} + +static zend_always_inline void zend_partial_args_overflow(zend_function *function, zend_string *symbol, uint32_t args, uint32_t expected, bool calling, bool prototype) { + const char *what = calling ? + "arguments" : "arguments or placeholders"; + const char *from = prototype ? + "application" : "implementation"; + + if (function->type == ZEND_USER_FUNCTION) { + zend_throw_error(NULL, + "too many %s for %s of %s, " + "%d given and a maximum of %d expected, declared in %s on line %d", + what, from, ZSTR_VAL(symbol), args, expected, + ZSTR_VAL(function->op_array.filename), function->op_array.line_start); + } else { + zend_throw_error(NULL, + "too many %s for %s of %s, %d given and a maximum of %d expected", + what, from, ZSTR_VAL(symbol), args, expected); + } +} + +void zend_partial_args_check(zend_execute_data *call) { + /* this is invoked by VM before the creation of zend_partial */ + zend_function *function = call->func; + + uint32_t num = ZEND_CALL_NUM_ARGS(call) + + (ZEND_PARTIAL_CALL_FLAG(call, ZEND_CALL_VARIADIC_PLACEHOLDER) ? -1 : 0); + + if (num < function->common.required_num_args) { + /* this check is delayed in the case of variadic application */ + if (ZEND_PARTIAL_CALL_FLAG(call, ZEND_CALL_VARIADIC_PLACEHOLDER)) { + return; + } + + zend_string *symbol = zend_partial_symbol_name(call, function); + zend_partial_args_underflow( + function, symbol, + num, function->common.required_num_args, false, true); + zend_string_release(symbol); + } else if (num > function->common.num_args && + !ZEND_PARTIAL_FUNC_FLAG(function, ZEND_ACC_VARIADIC)) { + zend_string *symbol = zend_partial_symbol_name(call, function); + zend_partial_args_overflow( + function, symbol, + num, function->common.num_args, false, true); + zend_string_release(symbol); + } +} + +static zend_always_inline uint32_t zend_partial_apply( + zval *pStart, zval *pEnd, + zval *cStart, zval *cEnd, + zval *fParam, bool call) { + + uint32_t pCount = 0; + + /* this optimizes the most general case, partial variadic application followed by + all arguments on call, and initial application */ + if ((pEnd - pStart) == 0 || + ((pEnd - pStart) == 1 && Z_IS_PLACEHOLDER_VARIADIC_P(pStart))) { + if ((pCount = (cEnd - cStart)) > 0) { + memcpy(fParam, cStart, sizeof(zval) * pCount); + } + + if (call) { + cStart = fParam; + cEnd = cStart + pCount; + while (cStart < cEnd) { + if (Z_IS_PLACEHOLDER_P(cStart)) { + ZVAL_UNDEF(cStart); + pCount--; + } + cStart++; + } + } + return pCount; + } + + /* this optimizes the second most general case: all arguments supplied upon first + application, followed by no arguments on call */ + if ((cEnd - cStart) == 0) { + if ((pCount = (pEnd - pStart)) > 0) { + memcpy(fParam, pStart, sizeof(zval) * pCount); + } + + if (call) { + cStart = fParam; + cEnd = cStart + pCount; + while (cStart < cEnd) { + if (Z_IS_PLACEHOLDER_P(cStart)) { + ZVAL_UNDEF(cStart); + pCount--; + } + cStart++; + } + } + return pCount; + } + + /* slow path is not able to handle all cases */ + while (pStart < pEnd) { + if (Z_IS_PLACEHOLDER_P(pStart)) { + if (cStart < cEnd) { + ZVAL_COPY_VALUE(fParam, cStart); + pCount++; + fParam++; + cStart++; + } + } else { + if (cStart < cEnd && Z_ISUNDEF_P(pStart)) { + ZVAL_COPY_VALUE(fParam, cStart); + pCount++; + fParam++; + cStart++; + } else { + ZVAL_COPY_VALUE(fParam, pStart); + pCount++; + fParam++; + } + } + pStart++; + } + + while (cStart < cEnd) { + ZVAL_COPY_VALUE(fParam, cStart); + pCount++; + fParam++; + cStart++; + } + + return pCount; +} + +ZEND_NAMED_FUNCTION(zend_partial_call_magic) +{ + zend_partial *partial = (zend_partial*) Z_OBJ_P(ZEND_THIS); + zend_object *object = NULL; + zval *params; + uint32_t num_params, num_all_params; + HashTable *named_args; + zend_fcall_info fci = empty_fcall_info; + zend_fcall_info_cache fcc = empty_fcall_info_cache; + + ZEND_PARSE_PARAMETERS_START(0, -1) + Z_PARAM_VARIADIC_WITH_NAMED(params, num_params, named_args) + ZEND_PARSE_PARAMETERS_END(); + + num_all_params = num_params + (named_args ? named_args->nNumUsed : 0); + + if (num_all_params < partial->prototype.common.required_num_args) { + zend_string *symbol = zend_partial_symbol_name(execute_data, &partial->prototype); + zend_partial_prototype_underflow( + &partial->prototype, symbol, num_all_params, + partial->prototype.common.required_num_args, + ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_VARIADIC)); + zend_string_release(symbol); + if (ZEND_PARTIAL_IS_CALL_TRAMPOLINE(&partial->prototype)) { + EG(trampoline).common.function_name = NULL; + } + RETURN_THROWS(); + } else if (num_all_params > partial->prototype.common.num_args && + !ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_VARIADIC)) { + zend_string *symbol = zend_partial_symbol_name(execute_data, &partial->prototype); + zend_partial_prototype_overflow( + &partial->prototype, symbol, num_all_params, + partial->prototype.common.num_args); + zend_string_release(symbol); + if (ZEND_PARTIAL_IS_CALL_TRAMPOLINE(&partial->prototype)) { + EG(trampoline).common.function_name = NULL; + } + RETURN_THROWS(); + } + + fci.size = sizeof(zend_fcall_info); + + if (UNEXPECTED(ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_FACTORY))) { + zend_class_entry *type = Z_CE(partial->This); + zval instance; + + if (type->create_object) { + ZVAL_OBJ(&instance, type->create_object(type)); + } else { + ZVAL_OBJ(&instance, zend_objects_new(type)); + + object_properties_init(Z_OBJ(instance), type); + } + + object = Z_OBJ(instance); + + if (ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_PASS)) { + /* nothing to pass any arguments too, so return immediately */ + RETURN_OBJ(object); + } + + GC_ADD_FLAGS(object, IS_OBJ_DESTRUCTOR_CALLED); + } else { + if (Z_TYPE(partial->This) == IS_OBJECT) { + object = Z_OBJ(partial->This); + } else if (Z_TYPE(partial->This) == IS_UNDEF && Z_CE(partial->This)) { + fcc.called_scope = Z_CE(partial->This); + } + } + + fci.retval = return_value; + fcc.function_handler = &partial->func; + + if (object) { + fci.object = object; + fcc.object = object; + } + + if (partial->named) { + if (!named_args) { + named_args = partial->named; + GC_ADDREF(named_args); + } else { + HashTable *nested = zend_array_dup(partial->named); + zend_hash_merge(nested, named_args, zval_copy_ctor, true); + named_args = nested; + } + fci.named_params = named_args; + } else { + fci.named_params = named_args; + } + + fci.params = ecalloc(sizeof(zval), partial->argc + num_params); + fci.param_count = zend_partial_apply( + partial->argv, partial->argv + partial->argc, + params ? params : NULL, + params ? params + num_params : NULL, fci.params, true); + + if (fci.param_count < partial->func.common.required_num_args) { + /* doesn't satisfy implementation */ + zend_string *symbol = zend_partial_symbol_name(execute_data, &partial->func); + zend_partial_args_underflow( + &partial->func, symbol, fci.param_count, + partial->func.common.required_num_args, true, false); + zend_string_release(symbol); + } else { + zend_call_function(&fci, &fcc); + } + + if (ZEND_PARTIAL_IS_CALL_TRAMPOLINE(&partial->prototype)) { + EG(trampoline).common.function_name = NULL; + } + + if (ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_FACTORY)) { + if (!EG(exception)) { + GC_DEL_FLAGS(object, IS_OBJ_DESTRUCTOR_CALLED); + } + zval_ptr_dtor(return_value); + RETVAL_OBJ(object); + } + + if (partial->named) { + zend_array_release(named_args); + } + efree(fci.params); +} + +void zend_partial_create(zval *result, uint32_t info, zval *this_ptr, zend_function *function, uint32_t argc, zval *argv, zend_array *extra_named_params) { + zend_function *prototype = NULL; + + ZVAL_OBJ(result, zend_partial_new(zend_ce_closure, info)); + + zend_partial *applied, *partial = (zend_partial*) Z_OBJ_P(result); + + if ((applied = zend_partial_fetch(this_ptr))) { + ZEND_ADD_CALL_FLAG(partial, ZEND_CALL_INFO(applied) & ~ZEND_APPLY_VARIADIC); + + function = &applied->func; + prototype = &applied->prototype; + + if (ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_FACTORY)) { + Z_CE(partial->This) = Z_CE(applied->This); + } + + partial->argv = ecalloc(applied->argc + argc, sizeof(zval)); + partial->argc = zend_partial_apply( + applied->argv, applied->argv + applied->argc, + argv, argv + argc, + partial->argv, false); + + if (extra_named_params) { + if (applied->named) { + partial->named = zend_array_dup(applied->named); + + zend_hash_merge(partial->named, extra_named_params, zval_copy_ctor, true); + } else { + partial->named = extra_named_params; + GC_ADDREF(extra_named_params); + } + } + } else { + partial->argv = ecalloc(argc, sizeof(zval)); + partial->argc = zend_partial_apply( + NULL, NULL, + argv, argv + argc, + partial->argv, false); + + if (extra_named_params) { + partial->named = extra_named_params; + GC_ADDREF(extra_named_params); + } + } + + memcpy(&partial->func, function, ZEND_PARTIAL_FUNC_SIZE(function)); + + ZEND_PARTIAL_FUNC_DEL(&partial->func, ZEND_ACC_CLOSURE); + ZEND_PARTIAL_FUNC_ADD(&partial->func, ZEND_ACC_IMMUTABLE); + + if (ZEND_PARTIAL_FUNC_FLAG(&partial->func, ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + ZEND_PARTIAL_FUNC_ADD(&partial->func, ZEND_ACC_TRAMPOLINE_PERMANENT); + } + + if (ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_FACTORY)) { + if (!Z_CE(partial->This)) { + Z_CE(partial->This) = Z_OBJCE_P(this_ptr); + } + + if (ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_PASS)) { + /* setting scope for pass function so that errors make sense */ + partial->func.common.scope = Z_CE(partial->This); + } + } + + ZEND_PARTIAL_FUNC_ADD(&partial->func, ZEND_ACC_FAKE_CLOSURE); + + if (partial->func.type == ZEND_USER_FUNCTION) { + zend_string_addref(partial->func.common.function_name); + + partial->func.op_array.refcount = NULL; + } + + if (!prototype) { + prototype = &partial->func; + } + + partial->func.common.prototype = zend_partial_signature_create(partial, prototype); + + if (!ZEND_PARTIAL_CALL_FLAG(partial, ZEND_APPLY_FACTORY)) { + /* partial info may contain ZEND_APPLY_VARIADIC */ + uint32_t backup_info = ZEND_CALL_INFO(partial); + + if(Z_TYPE_P(this_ptr) == IS_UNDEF && Z_CE_P(this_ptr)) { + ZVAL_COPY_VALUE(&partial->This, this_ptr); + } else if (Z_TYPE_P(this_ptr) == IS_OBJECT) { + zval *This; + if (instanceof_function(Z_OBJCE_P(this_ptr), zend_ce_closure)) { + if (zend_string_equals_ci( + partial->func.common.function_name, + ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) { + This = this_ptr; + } else { + This = zend_get_closure_this_ptr(this_ptr); + } + } else { + This = this_ptr; + } + ZVAL_COPY(&partial->This, This); + } + + ZEND_ADD_CALL_FLAG(partial, backup_info); + } + + zend_partial_trampoline_create(partial, &partial->trampoline); +} + +void zend_partial_bind(zval *result, zval *partial, zval *this_ptr, zend_class_entry *scope) { + zval This; + zend_partial *object = (zend_partial*) Z_OBJ_P(partial); + + ZVAL_UNDEF(&This); + + if (!this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) { + ZEND_ASSERT(scope && "scope must be set"); + + Z_CE(This) = scope; + } else { + ZVAL_COPY_VALUE(&This, this_ptr); + } + + zend_partial_create(result, ZEND_CALL_INFO(object), &This, + &object->func, object->argc, object->argv, object->named); + + zval *argv = object->argv, + *end = argv + object->argc; + + while (argv < end) { + Z_TRY_ADDREF_P(argv); + argv++; + } +} diff --git a/Zend/zend_partial.h b/Zend/zend_partial.h new file mode 100644 index 0000000000000..31d73bbda0413 --- /dev/null +++ b/Zend/zend_partial.h @@ -0,0 +1,42 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: krakjoe | + +----------------------------------------------------------------------+ +*/ +#ifndef ZEND_PARTIAL_H +#define ZEND_PARTIAL_H + +BEGIN_EXTERN_C() + +void zend_partial_startup(void); + +#define ZEND_APPLY_NORMAL (1<<16) +#define ZEND_APPLY_FACTORY (1<<17) +#define ZEND_APPLY_PASS (1<<18) +#define ZEND_APPLY_VARIADIC (1<<19) + +void zend_partial_create(zval *result, uint32_t info, zval *this_ptr, zend_function *function, uint32_t argc, zval *argv, zend_array *extra_named_params); + +void zend_partial_bind(zval *result, zval *partial, zval *this_ptr, zend_class_entry *scope); + +void zend_partial_args_check(zend_execute_data *call); + +zend_function *zend_partial_get_trampoline(zend_object *object); + +ZEND_NAMED_FUNCTION(zend_partial_call_magic); + +END_EXTERN_C() + +#endif diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 963362222d0eb..cb6f3437b7242 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -550,6 +550,10 @@ struct _zend_ast_ref { #define _IS_BOOL 18 #define _IS_NUMBER 19 +/* used for place holders */ +#define _IS_PLACEHOLDER_ARG 20 +#define _IS_PLACEHOLDER_VARIADIC 21 + static zend_always_inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e6a49d1c0d766..1e92f1c9e9b91 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5702,7 +5702,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL); + opline->extended_value, Z_OBJ_P(result)); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); @@ -8770,6 +8770,92 @@ ZEND_VM_HANDLER(200, ZEND_FETCH_GLOBALS, UNUSED, UNUSED) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(202, ZEND_SEND_PLACEHOLDER, UNUSED, UNUSED) +{ + USE_OPLINE + zval *arg; + zend_execute_data *call = EX(call); + + arg = ZEND_CALL_ARG(call, opline->op2.num); + + Z_TYPE_INFO_P(arg) = opline->op1.num; + + if (Z_TYPE_INFO_P(arg) == _IS_PLACEHOLDER_VARIADIC) { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_VARIADIC_PLACEHOLDER); + } + + ZEND_VM_NEXT_OPCODE(); +} + +ZEND_VM_HANDLER(203, ZEND_DO_FCALL_PARTIAL, ANY, ANY) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zval *result = NULL; + uint32_t info = ZEND_APPLY_NORMAL; + + if (opline->op1_type != IS_UNUSED) { + result = EX_VAR(opline->op1.var); + + if (!(call->func->common.fn_flags & ZEND_ACC_CTOR)) { + ZEND_ADD_CALL_FLAG_EX(info, ZEND_APPLY_PASS); + } + + ZEND_ADD_CALL_FLAG_EX(info, ZEND_APPLY_FACTORY); + } else if (opline->result_type != IS_UNUSED) { + result = EX_VAR(opline->result.var); + } + + if (ZEND_CALL_INFO(call) & ZEND_CALL_VARIADIC_PLACEHOLDER) { + ZEND_ADD_CALL_FLAG_EX(info, ZEND_APPLY_VARIADIC); + } + + if (result) { + zend_partial_create(result, info, + &call->This, call->func, + ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1), + ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS ? + call->extra_named_params : NULL); + + if (info & ZEND_APPLY_FACTORY) { + GC_ADD_FLAGS(Z_OBJ(call->This), IS_OBJ_DESTRUCTOR_CALLED); + OBJ_RELEASE(Z_OBJ(call->This)); + } + } else { + zend_vm_stack_free_args(call); + } + + if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_array_release(call->extra_named_params); + } + + if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + zend_free_trampoline(call->func); + } + + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { + OBJ_RELEASE(Z_OBJ(call->This)); + } else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); + } + + EX(call) = call->prev_execute_data; + + zend_vm_stack_free_call_frame(call); + + ZEND_VM_NEXT_OPCODE(); +} + +ZEND_VM_HANDLER(204, ZEND_CHECK_PARTIAL_ARGS, UNUSED, UNUSED) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + + SAVE_OPLINE(); + zend_partial_args_check(call); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + ZEND_VM_HANDLER(186, ZEND_ISSET_ISEMPTY_THIS, UNUSED, UNUSED) { USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 7fabd5d2673a5..ed3daffc7c5cb 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3507,6 +3507,65 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ ZEND_VM_LEAVE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_PARTIAL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zval *result = NULL; + uint32_t info = ZEND_APPLY_NORMAL; + + if (opline->op1_type != IS_UNUSED) { + result = EX_VAR(opline->op1.var); + + if (!(call->func->common.fn_flags & ZEND_ACC_CTOR)) { + ZEND_ADD_CALL_FLAG_EX(info, ZEND_APPLY_PASS); + } + + ZEND_ADD_CALL_FLAG_EX(info, ZEND_APPLY_FACTORY); + } else if (opline->result_type != IS_UNUSED) { + result = EX_VAR(opline->result.var); + } + + if (ZEND_CALL_INFO(call) & ZEND_CALL_VARIADIC_PLACEHOLDER) { + ZEND_ADD_CALL_FLAG_EX(info, ZEND_APPLY_VARIADIC); + } + + if (result) { + zend_partial_create(result, info, + &call->This, call->func, + ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1), + ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS ? + call->extra_named_params : NULL); + + if (info & ZEND_APPLY_FACTORY) { + GC_ADD_FLAGS(Z_OBJ(call->This), IS_OBJ_DESTRUCTOR_CALLED); + OBJ_RELEASE(Z_OBJ(call->This)); + } + } else { + zend_vm_stack_free_args(call); + } + + if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_array_release(call->extra_named_params); + } + + if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + zend_free_trampoline(call->func); + } + + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { + OBJ_RELEASE(Z_OBJ(call->This)); + } else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); + } + + EX(call) = call->prev_execute_data; + + zend_vm_stack_free_call_frame(call); + + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_FORWARD_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10156,7 +10215,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL); + opline->extended_value, Z_OBJ_P(result)); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); @@ -28388,7 +28447,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL); + opline->extended_value, Z_OBJ_P(result)); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); @@ -35196,7 +35255,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL); + opline->extended_value, Z_OBJ_P(result)); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); @@ -35384,6 +35443,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUS ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg; + zend_execute_data *call = EX(call); + + arg = ZEND_CALL_ARG(call, opline->op2.num); + + Z_TYPE_INFO_P(arg) = opline->op1.num; + + if (Z_TYPE_INFO_P(arg) == _IS_PLACEHOLDER_VARIADIC) { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_VARIADIC_PLACEHOLDER); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_PARTIAL_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + + SAVE_OPLINE(); + zend_partial_args_check(call); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -53541,6 +53627,9 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_LABEL, (void*)&&ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED_LABEL, (void*)&&ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_LABEL, + (void*)&&ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED_LABEL, + (void*)&&ZEND_DO_FCALL_PARTIAL_SPEC_LABEL, + (void*)&&ZEND_CHECK_PARTIAL_ARGS_SPEC_UNUSED_UNUSED_LABEL, (void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL, (void*)&&ZEND_JMP_FORWARD_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -54806,6 +54895,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) VM_TRACE(ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER) ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DO_FCALL_PARTIAL_SPEC): + VM_TRACE(ZEND_DO_FCALL_PARTIAL_SPEC) + ZEND_DO_FCALL_PARTIAL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_JMP_FORWARD_SPEC): VM_TRACE(ZEND_JMP_FORWARD_SPEC) ZEND_JMP_FORWARD_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57755,6 +57848,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) VM_TRACE(ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED) ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED): + VM_TRACE(ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED) + ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CHECK_PARTIAL_ARGS_SPEC_UNUSED_UNUSED): + VM_TRACE(ZEND_CHECK_PARTIAL_ARGS_SPEC_UNUSED_UNUSED) + ZEND_CHECK_PARTIAL_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED): VM_TRACE(ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED) ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -61581,6 +61682,9 @@ void zend_vm_init(void) ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_HANDLER, ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED_HANDLER, ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_DO_FCALL_PARTIAL_SPEC_HANDLER, + ZEND_CHECK_PARTIAL_ARGS_SPEC_UNUSED_UNUSED_HANDLER, ZEND_RECV_NOTYPE_SPEC_HANDLER, ZEND_JMP_FORWARD_SPEC_HANDLER, ZEND_NULL_HANDLER, @@ -62689,7 +62793,10 @@ void zend_vm_init(void) 2546, 2547, 2548, - 3452 + 2549, + 2550, + 2551, + 3455 }; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) zend_opcode_handler_funcs = labels; @@ -62862,7 +62969,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 = 2551 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2554 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -62870,7 +62977,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 = 2576 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2579 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -62878,7 +62985,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 = 2601 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2604 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -62889,17 +62996,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 = 2626 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2629 | 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 = 2651 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2654 | 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 = 2676 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2679 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -62910,17 +63017,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 = 2701 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2704 | 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 = 2726 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2729 | 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 = 2751 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2754 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_IDENTICAL: @@ -62931,14 +63038,14 @@ 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 = 2776 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2779 | 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 = 2851 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2854 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | 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 = 3076 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3079 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_IDENTICAL: @@ -62949,14 +63056,14 @@ 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 = 2926 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2929 | 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 = 3001 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3004 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | 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 = 3081 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3084 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_EQUAL: @@ -62967,12 +63074,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 = 2776 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2779 | 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 = 2851 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2854 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_EQUAL: @@ -62983,12 +63090,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 = 2926 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2929 | 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 = 3001 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3004 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_SMALLER: @@ -62996,12 +63103,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 = 3086 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3089 | 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 = 3161 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3164 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -63009,74 +63116,74 @@ 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 = 3236 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3239 | 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 = 3311 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3314 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if (op1_info == MAY_BE_LONG) { - spec = 3398 | SPEC_RULE_OP1; + spec = 3401 | SPEC_RULE_OP1; } else if (op1_info == MAY_BE_DOUBLE) { - spec = 3403 | SPEC_RULE_OP1; + spec = 3406 | 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 = 3408 | SPEC_RULE_OP1; + spec = 3411 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3386 | SPEC_RULE_RETVAL; + spec = 3389 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3388 | SPEC_RULE_RETVAL; + spec = 3391 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3390 | SPEC_RULE_RETVAL; + spec = 3393 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3392 | SPEC_RULE_RETVAL; + spec = 3395 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3394; + spec = 3397; } else if (op1_info == MAY_BE_LONG) { - spec = 3395; + spec = 3398; } break; case ZEND_POST_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3396; + spec = 3399; } else if (op1_info == MAY_BE_LONG) { - spec = 3397; + spec = 3400; } break; case ZEND_JMP: if (OP_JMP_ADDR(op, op->op1) > op) { - spec = 2550; + spec = 2553; } break; case ZEND_RECV: if (op->op2.num == MAY_BE_ANY) { - spec = 2549; + spec = 2552; } 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 = 3448; + spec = 3451; } 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 = 3443 | SPEC_RULE_OP1; + spec = 3446 | 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 = 3450 | SPEC_RULE_RETVAL; + spec = 3453 | SPEC_RULE_RETVAL; } break; case ZEND_FETCH_DIM_R: @@ -63084,17 +63191,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 = 3413 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3416 | 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 = 3449; + spec = 3452; } break; case ZEND_SEND_VAR: if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3438 | SPEC_RULE_OP1; + spec = 3441 | SPEC_RULE_OP1; } break; case ZEND_BW_OR: diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 8e500da57cbf3..e48479fbaf846 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1354,498 +1354,501 @@ _(2546, ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED) \ _(2547, ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED) \ _(2548, ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED) \ - _(2549, ZEND_RECV_NOTYPE_SPEC) \ - _(2550, ZEND_JMP_FORWARD_SPEC) \ - _(2556, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2557, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2558, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2549, ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED) \ + _(2550, ZEND_DO_FCALL_PARTIAL_SPEC) \ + _(2551, ZEND_CHECK_PARTIAL_ARGS_SPEC_UNUSED_UNUSED) \ + _(2552, ZEND_RECV_NOTYPE_SPEC) \ + _(2553, ZEND_JMP_FORWARD_SPEC) \ + _(2559, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2560, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2561, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2562, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2561, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2563, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2564, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2565, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2571, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2572, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2573, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2566, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2568, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2574, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2575, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2581, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2582, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2583, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2576, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2578, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2584, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2585, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2586, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2587, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2586, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2588, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2589, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2590, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2596, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2597, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2598, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2591, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2593, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2599, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2600, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2606, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2607, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2608, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2601, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2603, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2609, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2610, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2611, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2612, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2611, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2613, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2614, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2615, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2621, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2622, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2623, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2616, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2618, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2624, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2625, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2627, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2628, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2626, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2628, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2630, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2631, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2632, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2633, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2631, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2633, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2634, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2635, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2636, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2637, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2636, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2638, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2639, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2640, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2646, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2647, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2648, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2641, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2643, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2649, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2650, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2652, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2653, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2651, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2653, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2655, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2656, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2657, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2658, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2656, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2658, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2659, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2660, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2661, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2662, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2661, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2663, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2664, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2665, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2671, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2672, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2673, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2666, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2668, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2674, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2675, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2677, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2678, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2676, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2678, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2680, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2681, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2682, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2683, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2681, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2683, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2684, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2685, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2686, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2687, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2686, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2688, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2689, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2690, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2696, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2697, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2698, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2691, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2693, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2699, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2700, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2706, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2707, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2708, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2701, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2703, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2709, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2710, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2711, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2712, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2711, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2713, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2714, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2715, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2721, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2722, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2723, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2716, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2718, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2724, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2725, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2731, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2732, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2733, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2726, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2728, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2734, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2735, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2736, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2737, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2736, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2738, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2739, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2740, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2746, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2747, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2748, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2741, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2743, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2749, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2750, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2756, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2757, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2758, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2751, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2753, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2759, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2760, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2761, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2762, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2761, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2763, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2764, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2765, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2771, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2772, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2773, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2766, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2768, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2774, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2775, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2791, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2792, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2793, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2794, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2795, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2796, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2776, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2778, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2794, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2795, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2796, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2797, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2798, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2799, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2803, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2804, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2805, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2806, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2807, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2808, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2809, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2810, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2811, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2800, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2801, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2802, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2806, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2807, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2808, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2809, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2810, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2811, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2812, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2813, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2814, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2818, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2819, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2820, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2836, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2815, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2816, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2817, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2821, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2822, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2823, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2843, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2844, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2848, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2849, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2850, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2866, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2867, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2868, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2869, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2870, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2871, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2845, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2846, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2847, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2851, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2852, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2853, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2869, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2870, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2871, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2872, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2873, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2874, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2878, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2879, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2880, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2881, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2882, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2883, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2884, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2885, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2886, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2875, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2876, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2877, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2881, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2882, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2883, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2884, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2885, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2886, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2887, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2888, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2889, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2893, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2894, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2895, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2911, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2890, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2891, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2892, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2896, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2897, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2898, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2918, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2919, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2923, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2924, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2925, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2941, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2942, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2943, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2944, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2945, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2946, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2920, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2921, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2922, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2926, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2927, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2928, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2944, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2945, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2946, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2947, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2948, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2949, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2953, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2954, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2955, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2956, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2957, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2958, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2959, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2960, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2961, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2950, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2951, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2952, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2956, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2957, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2958, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2959, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2960, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2961, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2962, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2963, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2964, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2968, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2969, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2970, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2986, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2965, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2966, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2967, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2971, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2972, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2973, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2993, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(2994, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2998, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2999, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3000, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3016, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3017, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3018, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3019, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3020, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3021, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2995, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2996, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2997, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3001, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3002, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3003, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3019, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3020, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3021, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3022, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3023, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3024, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3028, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3029, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3030, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3031, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3032, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3033, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3034, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3035, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3036, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3025, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3026, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3027, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3031, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3032, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3033, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3034, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3035, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3036, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3037, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3038, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3039, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3043, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3044, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3045, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3061, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3040, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3041, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3042, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3046, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3047, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3048, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3068, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3069, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3073, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3074, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3075, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3076, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3080, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3081, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3085, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3089, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3090, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3091, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3070, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3071, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3072, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3076, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3077, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3078, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3079, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3083, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3084, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3088, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ _(3092, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ _(3093, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ _(3094, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3098, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3099, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3100, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3101, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3102, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3103, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3104, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3105, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3106, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3095, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3096, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3097, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3101, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3102, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3103, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3104, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3105, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3106, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3107, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(3108, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3109, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3113, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3114, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3115, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3116, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3117, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3118, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3119, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3120, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3121, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3110, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3111, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3112, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3116, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3117, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3118, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3119, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3120, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3121, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3122, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(3123, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3124, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3128, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3129, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3130, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3146, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3125, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3126, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3127, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3131, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3132, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3133, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3154, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3158, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3159, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3160, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3164, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3165, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3166, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3155, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3156, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3157, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3161, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3162, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3163, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ _(3167, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ _(3168, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ _(3169, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3173, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3174, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3175, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3176, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3177, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3178, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3179, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3180, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3181, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3170, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3171, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3172, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3176, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3177, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3178, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3179, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3180, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3181, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3182, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3183, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3184, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3188, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3189, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3190, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3191, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3192, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3193, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3194, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3195, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3196, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3185, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3186, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3187, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3191, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3192, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3193, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3194, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3195, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3196, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3197, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3198, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3204, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3205, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3221, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3206, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3207, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3208, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3229, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3233, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3234, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3235, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3239, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3240, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3241, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3230, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3231, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3232, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3236, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3237, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3238, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ _(3242, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ _(3243, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ _(3244, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3248, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3249, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3250, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3251, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3252, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3253, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3254, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3255, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3256, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3245, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3246, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3247, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3251, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3252, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3253, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3254, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3255, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3256, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3257, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(3258, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3259, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3263, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3264, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3265, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3266, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3267, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3268, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3269, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3270, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3271, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3260, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3261, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3262, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3266, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3267, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3268, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3269, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3270, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3271, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3272, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(3273, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3279, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3280, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3296, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3281, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3282, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3283, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3304, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3308, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3309, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3310, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3314, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3315, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3316, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3305, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3306, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3307, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3311, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3312, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3313, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ _(3317, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ _(3318, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ _(3319, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3323, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3324, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3325, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3326, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3327, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3328, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3329, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3330, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3331, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3320, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3321, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3322, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3326, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3327, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3328, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3329, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3330, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3331, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3332, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3333, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3334, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3338, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3339, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3340, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3341, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3342, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3343, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3344, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3345, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3346, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3335, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3336, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3337, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3341, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3342, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3343, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3344, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3345, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3346, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3347, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3348, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3354, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3355, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3371, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3356, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3357, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3358, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ _(3379, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3383, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3384, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3385, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3386, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3387, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3388, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3389, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ - _(3390, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3391, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3392, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3393, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ - _(3394, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3395, ZEND_POST_INC_LONG_SPEC_CV) \ - _(3396, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3397, ZEND_POST_DEC_LONG_SPEC_CV) \ - _(3398, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ - _(3399, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3400, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3380, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3381, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3382, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3386, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3387, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3388, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3389, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3390, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3391, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3392, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ + _(3393, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3394, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3395, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3396, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ + _(3397, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3398, ZEND_POST_INC_LONG_SPEC_CV) \ + _(3399, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3400, ZEND_POST_DEC_LONG_SPEC_CV) \ + _(3401, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ _(3402, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3403, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ - _(3404, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3405, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3403, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3405, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3406, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ _(3407, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3408, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ - _(3409, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3410, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3408, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3410, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3411, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ _(3412, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3414, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3415, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3413, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3415, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ _(3417, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3418, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3419, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3420, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3418, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3420, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3421, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3422, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3423, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3424, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3423, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ _(3425, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3426, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3427, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3433, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ - _(3434, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3435, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3428, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3430, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3436, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ _(3437, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3440, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ - _(3442, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ - _(3445, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ - _(3447, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ - _(3448, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ - _(3449, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ - _(3450, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ - _(3451, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ - _(3451+1, ZEND_NULL) + _(3438, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3440, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3443, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ + _(3445, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ + _(3448, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ + _(3450, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ + _(3451, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ + _(3452, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ + _(3453, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ + _(3454, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ + _(3454+1, ZEND_NULL) diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 83c3517807755..5a9cfcaf718a9 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -22,7 +22,7 @@ #include #include -static const char *zend_vm_opcodes_names[202] = { +static const char *zend_vm_opcodes_names[205] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -225,9 +225,12 @@ static const char *zend_vm_opcodes_names[202] = { "ZEND_CHECK_UNDEF_ARGS", "ZEND_FETCH_GLOBALS", "ZEND_VERIFY_NEVER_TYPE", + "ZEND_SEND_PLACEHOLDER", + "ZEND_DO_FCALL_PARTIAL", + "ZEND_CHECK_PARTIAL_ARGS", }; -static uint32_t zend_vm_opcodes_flags[202] = { +static uint32_t zend_vm_opcodes_flags[205] = { 0x00000000, 0x00000b0b, 0x00000b0b, @@ -430,6 +433,9 @@ static uint32_t zend_vm_opcodes_flags[202] = { 0x00000101, 0x00000101, 0x00000101, + 0x00000101, + 0x00000000, + 0x00000101, }; ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(zend_uchar opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 94e74c0a57f12..e5d5effbebbbe 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -285,7 +285,10 @@ END_EXTERN_C() #define ZEND_CHECK_UNDEF_ARGS 199 #define ZEND_FETCH_GLOBALS 200 #define ZEND_VERIFY_NEVER_TYPE 201 +#define ZEND_SEND_PLACEHOLDER 202 +#define ZEND_DO_FCALL_PARTIAL 203 +#define ZEND_CHECK_PARTIAL_ARGS 204 -#define ZEND_VM_LAST_OPCODE 201 +#define ZEND_VM_LAST_OPCODE 204 #endif diff --git a/configure.ac b/configure.ac index e63c0b969fd34..0424fe1a659e4 100644 --- a/configure.ac +++ b/configure.ac @@ -1608,7 +1608,7 @@ PHP_ADD_SOURCES(Zend, \ zend_closures.c zend_weakrefs.c zend_float.c zend_string.c zend_signal.c zend_generators.c \ zend_virtual_cwd.c zend_ast.c zend_objects.c zend_object_handlers.c zend_objects_API.c \ zend_default_classes.c zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_gdb.c \ - zend_observer.c zend_system_id.c zend_enum.c zend_fibers.c \ + zend_observer.c zend_system_id.c zend_enum.c zend_fibers.c zend_partial.c \ Optimizer/zend_optimizer.c \ Optimizer/pass1.c \ Optimizer/pass3.c \ diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 5ff8dc6f515ab..ed2423cd6a479 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -200,6 +200,7 @@ static zend_function *_copy_function(zend_function *fptr) /* {{{ */ zend_function *copy_fptr; copy_fptr = emalloc(sizeof(zend_function)); memcpy(copy_fptr, fptr, sizeof(zend_function)); + copy_fptr->internal_function.fn_flags &= ~ZEND_ACC_TRAMPOLINE_PERMANENT; copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name); return copy_fptr; } else { @@ -588,6 +589,10 @@ static void _class_const_string(smart_str *str, char *name, zend_class_constant static zend_op *get_recv_op(zend_op_array *op_array, uint32_t offset) { + if (op_array->fn_flags & ZEND_ACC_PARTIAL) { + op_array = (zend_op_array*) op_array->prototype; + } + zend_op *op = op_array->opcodes; zend_op *end = op + op_array->last; @@ -600,15 +605,21 @@ static zend_op *get_recv_op(zend_op_array *op_array, uint32_t offset) } ++op; } - ZEND_ASSERT(0 && "Failed to find op"); + return NULL; } static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) { + zend_op *recv = get_recv_op(op_array, offset); - if (!recv || recv->opcode != ZEND_RECV_INIT) { + + if (!recv) { return NULL; } + + if (recv->opcode != ZEND_RECV_INIT) { + return NULL; + } return RT_CONSTANT(recv, recv->op2); } @@ -803,6 +814,9 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) { smart_str_appends(str, "abstract "); } + if (fptr->common.fn_flags & ZEND_ACC_PARTIAL) { + smart_str_appends(str, "partial "); + } if (fptr->common.fn_flags & ZEND_ACC_FINAL) { smart_str_appends(str, "final "); } @@ -1289,6 +1303,31 @@ static void reflection_extension_factory(zval *object, const char *name_str) } /* }}} */ +static zend_always_inline uint32_t reflection_parameter_partial_offset(zend_function *fptr, zend_arg_info *info) { + zend_arg_info *arg = fptr->common.prototype->common.arg_info, + *end = arg + fptr->common.prototype->common.num_args; + uint32_t offset = 0; + + if (fptr->type == ZEND_USER_FUNCTION && + fptr->op_array.opcodes == &EG(call_trampoline_op)) { + return 0; + } + + if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) { + end++; + } + + while (arg < end) { + if (zend_string_equals_ci(info->name, arg->name)) { + return offset; + } + offset++; + arg++; + } + ZEND_ASSERT(0); + return -1; +} + /* {{{ reflection_parameter_factory */ static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, bool required, zval *object) { @@ -1300,7 +1339,11 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje intern = Z_REFLECTION_P(object); reference = (parameter_reference*) emalloc(sizeof(parameter_reference)); reference->arg_info = arg_info; - reference->offset = offset; + if (fptr->common.fn_flags & ZEND_ACC_PARTIAL) { + reference->offset = reflection_parameter_partial_offset(fptr, arg_info); + } else { + reference->offset = offset; + } reference->required = required; reference->fptr = fptr; intern->ptr = reference; @@ -1569,7 +1612,9 @@ ZEND_METHOD(ReflectionFunction, __construct) zval_ptr_dtor(reflection_prop_name(object)); } - ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name); + if (fptr->common.function_name) { + ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name); + } intern->ptr = fptr; intern->ref_type = REF_TYPE_FUNCTION; if (closure_obj) { @@ -1622,7 +1667,21 @@ ZEND_METHOD(ReflectionFunctionAbstract, isClosure) RETURN_THROWS(); } GET_REFLECTION_OBJECT_PTR(fptr); - RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE); + RETURN_BOOL(fptr->common.fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_PARTIAL)); +} +/* }}} */ + +/* {{{ Returns whether this is a partial closure */ +ZEND_METHOD(ReflectionFunctionAbstract, isPartial) +{ + reflection_object *intern; + zend_function *fptr; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + GET_REFLECTION_OBJECT_PTR(fptr); + RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_PARTIAL); } /* }}} */ @@ -1638,7 +1697,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getClosureThis) GET_REFLECTION_OBJECT(); if (!Z_ISUNDEF(intern->obj)) { closure_this = zend_get_closure_this_ptr(&intern->obj); - if (!Z_ISUNDEF_P(closure_this)) { + if (closure_this && Z_TYPE_P(closure_this) == IS_OBJECT) { RETURN_OBJ_COPY(Z_OBJ_P(closure_this)); } } @@ -1657,6 +1716,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass) GET_REFLECTION_OBJECT(); if (!Z_ISUNDEF(intern->obj)) { closure_func = zend_get_closure_method_def(Z_OBJ(intern->obj)); + if (closure_func && closure_func->common.scope) { zend_reflection_class_factory(closure_func->common.scope, return_value); } diff --git a/win32/build/config.w32 b/win32/build/config.w32 index 28f9a1f320793..ae1dd3823f09f 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -238,7 +238,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \ zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c zend_weakrefs.c \ zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c \ zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_observer.c zend_system_id.c \ - zend_enum.c zend_fibers.c"); + zend_enum.c zend_fibers.c zend_partial.c"); ADD_SOURCES("Zend\\Optimizer", "zend_optimizer.c pass1.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c escape_analysis.c compact_vars.c dce.c sccp.c scdf.c"); var FIBER_ASSEMBLER = X64 ? PATH_PROG('ML64') : PATH_PROG('ML');