From 8c25a2346587c2f6ac9122ac9786c21ac51402a0 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 27 Nov 2022 17:48:42 +0100 Subject: [PATCH 1/5] Implement pattern matching --- Zend/tests/pattern_matching/is/and.phpt | 29 + Zend/tests/pattern_matching/is/array.phpt | 30 + .../pattern_matching/is/array_mixed_keys.phpt | 10 + Zend/tests/pattern_matching/is/bail.phpt | 43 + Zend/tests/pattern_matching/is/binding.phpt | 87 ++ .../pattern_matching/is/binding_destruct.phpt | 28 + .../is/binding_in_or_001.phpt | 8 + .../is/binding_in_or_002.phpt | 8 + .../pattern_matching/is/class_constant.phpt | 44 + .../is/compound_parentheses_1.phpt | 8 + .../is/compound_parentheses_2.phpt | 8 + .../pattern_matching/is/delayed_binding.phpt | 50 + Zend/tests/pattern_matching/is/object.phpt | 127 +++ .../pattern_matching/is/object_shorthand.phpt | 22 + Zend/tests/pattern_matching/is/or.phpt | 24 + Zend/tests/pattern_matching/is/range.phpt | 41 + Zend/tests/pattern_matching/is/scalar.phpt | 26 + Zend/tests/pattern_matching/is/type.phpt | 25 + Zend/tests/pattern_matching/is/wildcard.phpt | 24 + Zend/tests/pattern_matching/match/basic.phpt | 80 ++ Zend/tests/pattern_matching/match/scalar.phpt | 14 + Zend/zend_ast.h | 14 + Zend/zend_compile.c | 249 ++++- Zend/zend_compile.h | 7 + Zend/zend_execute.c | 1 + Zend/zend_execute_API.c | 3 + Zend/zend_globals.h | 3 + Zend/zend_language_parser.y | 141 ++- Zend/zend_language_scanner.l | 12 + Zend/zend_opcode.c | 3 +- Zend/zend_pattern_matching.c | 370 +++++++ Zend/zend_pattern_matching.h | 47 + Zend/zend_vm_def.h | 11 + Zend/zend_vm_execute.h | 202 ++-- Zend/zend_vm_handlers.h | 923 +++++++++--------- Zend/zend_vm_opcodes.c | 6 +- Zend/zend_vm_opcodes.h | 3 +- configure.ac | 1 + ext/tokenizer/tokenizer_data.c | 3 + ext/tokenizer/tokenizer_data.stub.php | 15 + ext/tokenizer/tokenizer_data_arginfo.h | 5 +- win32/build/config.w32 | 2 +- 42 files changed, 2187 insertions(+), 570 deletions(-) create mode 100644 Zend/tests/pattern_matching/is/and.phpt create mode 100644 Zend/tests/pattern_matching/is/array.phpt create mode 100644 Zend/tests/pattern_matching/is/array_mixed_keys.phpt create mode 100644 Zend/tests/pattern_matching/is/bail.phpt create mode 100644 Zend/tests/pattern_matching/is/binding.phpt create mode 100644 Zend/tests/pattern_matching/is/binding_destruct.phpt create mode 100644 Zend/tests/pattern_matching/is/binding_in_or_001.phpt create mode 100644 Zend/tests/pattern_matching/is/binding_in_or_002.phpt create mode 100644 Zend/tests/pattern_matching/is/class_constant.phpt create mode 100644 Zend/tests/pattern_matching/is/compound_parentheses_1.phpt create mode 100644 Zend/tests/pattern_matching/is/compound_parentheses_2.phpt create mode 100644 Zend/tests/pattern_matching/is/delayed_binding.phpt create mode 100644 Zend/tests/pattern_matching/is/object.phpt create mode 100644 Zend/tests/pattern_matching/is/object_shorthand.phpt create mode 100644 Zend/tests/pattern_matching/is/or.phpt create mode 100644 Zend/tests/pattern_matching/is/range.phpt create mode 100644 Zend/tests/pattern_matching/is/scalar.phpt create mode 100644 Zend/tests/pattern_matching/is/type.phpt create mode 100644 Zend/tests/pattern_matching/is/wildcard.phpt create mode 100644 Zend/tests/pattern_matching/match/basic.phpt create mode 100644 Zend/tests/pattern_matching/match/scalar.phpt create mode 100644 Zend/zend_pattern_matching.c create mode 100644 Zend/zend_pattern_matching.h diff --git a/Zend/tests/pattern_matching/is/and.phpt b/Zend/tests/pattern_matching/is/and.phpt new file mode 100644 index 0000000000000..9cb597f2b27e6 --- /dev/null +++ b/Zend/tests/pattern_matching/is/and.phpt @@ -0,0 +1,29 @@ +--TEST-- +And pattern +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) diff --git a/Zend/tests/pattern_matching/is/array.phpt b/Zend/tests/pattern_matching/is/array.phpt new file mode 100644 index 0000000000000..43f452e62ddf3 --- /dev/null +++ b/Zend/tests/pattern_matching/is/array.phpt @@ -0,0 +1,30 @@ +--TEST-- +Array pattern +--FILE-- + 42]); +var_dump([42, 43] is [42]); +var_dump([42, 43] is [42, ...]); +var_dump([42] is [$a]); +var_dump($a); + +?> +--EXPECT-- +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +bool(true) +int(42) diff --git a/Zend/tests/pattern_matching/is/array_mixed_keys.phpt b/Zend/tests/pattern_matching/is/array_mixed_keys.phpt new file mode 100644 index 0000000000000..339efe571ca26 --- /dev/null +++ b/Zend/tests/pattern_matching/is/array_mixed_keys.phpt @@ -0,0 +1,10 @@ +--TEST-- +Array pattern with mixed implicit and explicit keys +--FILE-- + 'bar']); + +?> +--EXPECTF-- +Fatal error: Must not mix implicit and explicit array keys in array pattern in %s on line %d diff --git a/Zend/tests/pattern_matching/is/bail.phpt b/Zend/tests/pattern_matching/is/bail.phpt new file mode 100644 index 0000000000000..9e9437d10414b --- /dev/null +++ b/Zend/tests/pattern_matching/is/bail.phpt @@ -0,0 +1,43 @@ +--TEST-- +Object pattern matching +--FILE-- +getMessage(), "\n"; +} + +try { + var_dump($o is parent {}); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump($o is static {}); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} + +class C { + public static function test($o) { + try { + var_dump($o is parent {}); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + } + } +} + +C::test($o); + +?> +--EXPECT-- +Cannot access "self" when no class scope is active +Cannot access "parent" when no class scope is active +Cannot access "static" when no class scope is active +Cannot access "parent" when current class scope has no parent diff --git a/Zend/tests/pattern_matching/is/binding.phpt b/Zend/tests/pattern_matching/is/binding.phpt new file mode 100644 index 0000000000000..4ce5dc6e325ff --- /dev/null +++ b/Zend/tests/pattern_matching/is/binding.phpt @@ -0,0 +1,87 @@ +--TEST-- +Binding pattern +--FILE-- + +--EXPECT-- +bool(true) +int(10) +bool(true) +string(11) "Hello world" +bool(true) +int(42) +bool(false) +int(42) +bool(true) +int(43) +bool(false) +int(43) +bool(true) +int(1) +int(2) +int(3) +int(4) +bool(false) +bool(true) +int(1) +int(2) +int(3) +int(4) +int(5) +int(6) +int(7) +int(8) +int(9) +int(10) diff --git a/Zend/tests/pattern_matching/is/binding_destruct.phpt b/Zend/tests/pattern_matching/is/binding_destruct.phpt new file mode 100644 index 0000000000000..7ceea9972c619 --- /dev/null +++ b/Zend/tests/pattern_matching/is/binding_destruct.phpt @@ -0,0 +1,28 @@ +--TEST-- +Object pattern matching destructor +--FILE-- +getMessage(), "\n"; +} + +var_dump($foo); +var_dump($bar); + +?> +--EXPECT-- +Here +int(42) +int(42) diff --git a/Zend/tests/pattern_matching/is/binding_in_or_001.phpt b/Zend/tests/pattern_matching/is/binding_in_or_001.phpt new file mode 100644 index 0000000000000..cc4a7e67c81e7 --- /dev/null +++ b/Zend/tests/pattern_matching/is/binding_in_or_001.phpt @@ -0,0 +1,8 @@ +--TEST-- +Must not bind to variables in | pattern +--FILE-- + +--EXPECTF-- +Fatal error: Must not bind to variables inside | pattern in %s on line %d diff --git a/Zend/tests/pattern_matching/is/binding_in_or_002.phpt b/Zend/tests/pattern_matching/is/binding_in_or_002.phpt new file mode 100644 index 0000000000000..23beb97e6c667 --- /dev/null +++ b/Zend/tests/pattern_matching/is/binding_in_or_002.phpt @@ -0,0 +1,8 @@ +--TEST-- +Must not bind to variables in | pattern +--FILE-- + +--EXPECTF-- +Fatal error: Must not bind to variables inside | pattern in %s on line %d diff --git a/Zend/tests/pattern_matching/is/class_constant.phpt b/Zend/tests/pattern_matching/is/class_constant.phpt new file mode 100644 index 0000000000000..62573440b2a3d --- /dev/null +++ b/Zend/tests/pattern_matching/is/class_constant.phpt @@ -0,0 +1,44 @@ +--TEST-- +Class constant pattern +--FILE-- +getMessage(), "\n"; +} +try { + var_dump('a' is Foo::C); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +Foo::test(); +var_dump(Bar::A is Bar::A); +var_dump('foo' is Bar::A); + +?> +--EXPECT-- +bool(true) +bool(false) +Cannot access private constant Foo::B +Undefined constant Foo::C +bool(true) +bool(false) +bool(true) +bool(false) diff --git a/Zend/tests/pattern_matching/is/compound_parentheses_1.phpt b/Zend/tests/pattern_matching/is/compound_parentheses_1.phpt new file mode 100644 index 0000000000000..63f8230d4a1e7 --- /dev/null +++ b/Zend/tests/pattern_matching/is/compound_parentheses_1.phpt @@ -0,0 +1,8 @@ +--TEST-- +Nested compound patterns require parentheses +--FILE-- + +--EXPECTF-- +Fatal error: Nested compound pattern must be parenthesized in %s on line %d diff --git a/Zend/tests/pattern_matching/is/compound_parentheses_2.phpt b/Zend/tests/pattern_matching/is/compound_parentheses_2.phpt new file mode 100644 index 0000000000000..8694c7705bd9f --- /dev/null +++ b/Zend/tests/pattern_matching/is/compound_parentheses_2.phpt @@ -0,0 +1,8 @@ +--TEST-- +Nested compound patterns require parentheses +--FILE-- + +--EXPECTF-- +Fatal error: Nested compound pattern must be parenthesized in %s on line %d diff --git a/Zend/tests/pattern_matching/is/delayed_binding.phpt b/Zend/tests/pattern_matching/is/delayed_binding.phpt new file mode 100644 index 0000000000000..7e3edb324173d --- /dev/null +++ b/Zend/tests/pattern_matching/is/delayed_binding.phpt @@ -0,0 +1,50 @@ +--TEST-- +Delayed binding +--FILE-- + +--EXPECTF-- +bool(true) +int(1) +int(2) +bool(false) + +Warning: Undefined variable $a in %s on line %d + +Warning: Undefined variable $b in %s on line %d +NULL +NULL +bool(true) + +Warning: Undefined variable $b in %s on line %d +object(stdClass)#2 (0) { +} +NULL +bool(false) + +Warning: Undefined variable $a in %s on line %d + +Warning: Undefined variable $b in %s on line %d +NULL +NULL diff --git a/Zend/tests/pattern_matching/is/object.phpt b/Zend/tests/pattern_matching/is/object.phpt new file mode 100644 index 0000000000000..6f05a7211354b --- /dev/null +++ b/Zend/tests/pattern_matching/is/object.phpt @@ -0,0 +1,127 @@ +--TEST-- +Object pattern matching +--FILE-- + +--EXPECTF-- +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) +bool(true) +bool(false) + +Warning: Undefined property: Foo::$b in %s on line %d +bool(false) +bool(false) +bool(true) +bool(false) + +Warning: Undefined property: Bar::$b in %s on line %d +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) diff --git a/Zend/tests/pattern_matching/is/object_shorthand.phpt b/Zend/tests/pattern_matching/is/object_shorthand.phpt new file mode 100644 index 0000000000000..ad269ae855342 --- /dev/null +++ b/Zend/tests/pattern_matching/is/object_shorthand.phpt @@ -0,0 +1,22 @@ +--TEST-- +Object pattern matching +--FILE-- + +--EXPECTF-- +bool(true) +int(1) +bool(false) + +Warning: Undefined variable $b in %s on line %d +NULL diff --git a/Zend/tests/pattern_matching/is/or.phpt b/Zend/tests/pattern_matching/is/or.phpt new file mode 100644 index 0000000000000..4294332d81a1f --- /dev/null +++ b/Zend/tests/pattern_matching/is/or.phpt @@ -0,0 +1,24 @@ +--TEST-- +Or pattern +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) diff --git a/Zend/tests/pattern_matching/is/range.phpt b/Zend/tests/pattern_matching/is/range.phpt new file mode 100644 index 0000000000000..90616c6525de9 --- /dev/null +++ b/Zend/tests/pattern_matching/is/range.phpt @@ -0,0 +1,41 @@ +--TEST-- +Or pattern +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(false) diff --git a/Zend/tests/pattern_matching/is/scalar.phpt b/Zend/tests/pattern_matching/is/scalar.phpt new file mode 100644 index 0000000000000..fdcd7d8f9c3af --- /dev/null +++ b/Zend/tests/pattern_matching/is/scalar.phpt @@ -0,0 +1,26 @@ +--TEST-- +Scalar pattern matching +--FILE-- + +--EXPECT-- +bool(true) +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +bool(false) +bool(true) diff --git a/Zend/tests/pattern_matching/is/type.phpt b/Zend/tests/pattern_matching/is/type.phpt new file mode 100644 index 0000000000000..252e51bcc9469 --- /dev/null +++ b/Zend/tests/pattern_matching/is/type.phpt @@ -0,0 +1,25 @@ +--TEST-- +Type pattern matching +--FILE-- + +--EXPECT-- +bool(true) +bool(false) +bool(false) +bool(false) +bool(true) +bool(true) +bool(false) diff --git a/Zend/tests/pattern_matching/is/wildcard.phpt b/Zend/tests/pattern_matching/is/wildcard.phpt new file mode 100644 index 0000000000000..0cb473e725f34 --- /dev/null +++ b/Zend/tests/pattern_matching/is/wildcard.phpt @@ -0,0 +1,24 @@ +--TEST-- +Wildcard pattern matching +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/Zend/tests/pattern_matching/match/basic.phpt b/Zend/tests/pattern_matching/match/basic.phpt new file mode 100644 index 0000000000000..0d264abf59937 --- /dev/null +++ b/Zend/tests/pattern_matching/match/basic.phpt @@ -0,0 +1,80 @@ +--TEST-- +Test basic pattern matching +--FILE-- + wrong(), + is 0 => wrong(), + is [] => wrong(), + is null => 'Literal pattern with null', +}); + +var_dump(match (true) { + is false => wrong(), + is true => 'Literal pattern with bool', +}); + +var_dump(match (4) { + is 1 => wrong(), + is 2 => wrong(), + is 3 => wrong(), + is 4 => 'Literal pattern with int', + is 5 => wrong(), + is 6 => wrong(), +}); + +var_dump(match ('e') { + is 'a' => wrong(), + is 'b' => wrong(), + is 'c' => wrong(), + is 'd' => wrong(), + is 'e' => 'Literal pattern with string', + is 'f' => wrong(), + is 'g' => wrong(), +}); + +var_dump(match ('Foo') { + is 1 => wrong(), + is 2 => wrong(), + is 3 => wrong(), + is $a => 'Identifier pattern: ' . $a, + is 5 => wrong(), + is 6 => wrong(), +}); + +var_dump(match ('Foo') { + is 1 => wrong(), + is 2 => wrong(), + is 3 => wrong(), + is * => 'Wildcard pattern', +}); + +var_dump(match (15) { + is 0 ..< 10 => wrong(), + is 10 ..< 20 => 'Range pattern', + is 20 ..< 30 => wrong(), +}); + +// var_dump(match ('foo') { +// is 'bar' => wrong(), +// is Foo::FOO => 'Class constant literal', +// }); + +?> +--EXPECT-- +string(25) "Literal pattern with null" +string(25) "Literal pattern with bool" +string(24) "Literal pattern with int" +string(27) "Literal pattern with string" +string(23) "Identifier pattern: Foo" +string(16) "Wildcard pattern" +string(13) "Range pattern" diff --git a/Zend/tests/pattern_matching/match/scalar.phpt b/Zend/tests/pattern_matching/match/scalar.phpt new file mode 100644 index 0000000000000..73035674eeca8 --- /dev/null +++ b/Zend/tests/pattern_matching/match/scalar.phpt @@ -0,0 +1,14 @@ +--TEST-- +Scalar pattern matching +--FILE-- + 1, + is 2 => 2, + is 3 => 3, +}); + +?> +--EXPECT-- +int(2) diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index d3689af53ff7e..d6cb748f3fcbe 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -69,12 +69,15 @@ enum _zend_ast_kind { ZEND_AST_ATTRIBUTE_GROUP, ZEND_AST_MATCH_ARM_LIST, ZEND_AST_MODIFIER_LIST, + ZEND_AST_OBJECT_PATTERN_ELEMENT_LIST, + ZEND_AST_ARRAY_PATTERN_ELEMENT_LIST, /* 0 child nodes */ ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_TYPE, ZEND_AST_CONSTANT_CLASS, ZEND_AST_CALLABLE_CONVERT, + ZEND_AST_WILDCARD_PATTERN, /* 1 child node */ ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT, @@ -110,6 +113,8 @@ enum _zend_ast_kind { ZEND_AST_BREAK, ZEND_AST_CONTINUE, ZEND_AST_PROPERTY_HOOK_SHORT_BODY, + ZEND_AST_TYPE_PATTERN, + ZEND_AST_ARRAY_PATTERN, /* 2 child nodes */ ZEND_AST_DIM = 2 << ZEND_AST_NUM_CHILDREN_SHIFT, @@ -152,6 +157,15 @@ enum _zend_ast_kind { ZEND_AST_MATCH_ARM, ZEND_AST_NAMED_ARG, ZEND_AST_PARENT_PROPERTY_HOOK_CALL, + ZEND_AST_IS, + ZEND_AST_OR_PATTERN, + ZEND_AST_AND_PATTERN, + ZEND_AST_OBJECT_PATTERN, + ZEND_AST_OBJECT_PATTERN_ELEMENT, + ZEND_AST_RANGE_PATTERN, + ZEND_AST_ARRAY_PATTERN_ELEMENT, + ZEND_AST_BINDING_PATTERN, + ZEND_AST_CLASS_CONST_PATTERN, /* 3 child nodes */ ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT, diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8e8d8d4075644..f3e5a0cdf5adf 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6397,6 +6397,10 @@ static bool can_match_use_jumptable(zend_ast_list *arms) { for (uint32_t j = 0; j < conds->children; j++) { zend_ast **cond_ast = &conds->child[j]; + if ((*cond_ast)->kind == ZEND_AST_IS) { + return 0; + } + zend_eval_const_expr(cond_ast); if ((*cond_ast)->kind != ZEND_AST_ZVAL) { return 0; @@ -6412,6 +6416,8 @@ static bool can_match_use_jumptable(zend_ast_list *arms) { return 1; } +static void zend_compile_pattern(zend_ast **ast_ptr, void *context); + static void zend_compile_match(znode *result, zend_ast *ast) { zend_ast *expr_ast = ast->child[0]; @@ -6472,14 +6478,34 @@ static void zend_compile_match(znode *result, zend_ast *ast) for (uint32_t j = 0; j < conds->children; j++) { zend_ast *cond_ast = conds->child[j]; - znode cond_node; - zend_compile_expr(&cond_node, cond_ast); + if (cond_ast->kind != ZEND_AST_IS) { + znode cond_node; + zend_compile_expr(&cond_node, cond_ast); - uint32_t opcode = (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE_STRICT : ZEND_IS_IDENTICAL; - zend_op *opline = zend_emit_op(NULL, opcode, &expr_node, &cond_node); - SET_NODE(opline->result, &case_node); - if (opline->op1_type == IS_CONST) { - Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1)); + uint32_t opcode = (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE_STRICT : ZEND_IS_IDENTICAL; + zend_op *opline = zend_emit_op(NULL, opcode, &expr_node, &cond_node); + SET_NODE(opline->result, &case_node); + if (opline->op1_type == IS_CONST) { + Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1)); + } + } else { + zend_ast **pattern_ast_ptr = &cond_ast->child[1]; + + zend_compile_pattern(pattern_ast_ptr, NULL); + zval pattern_zv; + ZVAL_AST(&pattern_zv, zend_ast_copy(*pattern_ast_ptr)); + zend_ast_destroy(*pattern_ast_ptr); + *pattern_ast_ptr = zend_ast_create_zval(&pattern_zv); + + znode pattern_node; + pattern_node.op_type = IS_CONST; + ZVAL_COPY(&pattern_node.u.constant, &pattern_zv); + + zend_op *opline = zend_emit_op_tmp(NULL, ZEND_IS, &expr_node, &pattern_node); + SET_NODE(opline->result, &case_node); + if (opline->op1_type == IS_CONST) { + Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1)); + } } jmpnz_opnums[cond_count] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0); @@ -6598,6 +6624,212 @@ static void zend_compile_match(znode *result, zend_ast *ast) efree(jmp_end_opnums); } +static void zend_compile_pattern_class_name(zend_ast *ast) +{ + zend_ast *class_name_ast = ast->child[0]; + ZEND_ASSERT(class_name_ast->kind == ZEND_AST_ZVAL); + + zend_string *class_name = zend_ast_get_str(class_name_ast); + uint32_t fetch_type = zend_get_class_fetch_type(class_name); + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + case ZEND_FETCH_CLASS_PARENT: + case ZEND_FETCH_CLASS_STATIC: + /* For the const-eval representation store the fetch type instead of the name. */ + zend_string_release(class_name); + ast->child[0] = NULL; + ast->attr = fetch_type; + return; + case ZEND_FETCH_CLASS_DEFAULT: { + zend_string *tmp = zend_resolve_class_name_ast(class_name_ast); + zend_string_release_ex(class_name, 0); + if (tmp != class_name) { + zval *zv = zend_ast_get_zval(class_name_ast); + ZVAL_STR(zv, tmp); + class_name_ast->attr = ZEND_NAME_FQ; + } + break; + } + EMPTY_SWITCH_DEFAULT_CASE() + } +} + +static void zend_compile_object_pattern(zend_ast **ast_ptr) +{ + zend_ast *ast = *ast_ptr; + zend_compile_pattern_class_name(ast); +} + +static zend_type zend_compile_single_typename(zend_ast *ast); + +static void zend_compile_type_pattern(zend_ast **ast_ptr) +{ + zend_ast *type_pattern_ast = *ast_ptr; + zend_ast *type_ast = type_pattern_ast->child[0]; + bool nullable = type_ast->attr & ZEND_TYPE_NULLABLE; + type_ast->attr &= ~ZEND_TYPE_NULLABLE; + zend_type type = zend_compile_single_typename(type_ast); + if (nullable) { + ZEND_TYPE_FULL_MASK(type) |= MAY_BE_NULL; + } + uint32_t type_mask = ZEND_TYPE_PURE_MASK(type); + + // FIXME: Make sure the type mask actually fits + type_pattern_ast->attr = (uint16_t) type_mask; + + zend_ast_destroy(type_ast); + type_pattern_ast->child[0] = NULL; + + if (ZEND_TYPE_IS_COMPLEX(type)) { + zend_string *class_name = ZEND_TYPE_NAME(type); + type_pattern_ast->child[0] = zend_ast_create_zval_from_str(class_name); + } +} + +static void zend_compile_class_const_pattern(zend_ast **ast_ptr) +{ + // zend_ast *ast = *ast_ptr; + // FIXME: Compiling the class name breaks zend_get_class_constant_ex. + // zend_compile_pattern_class_name(ast); +} + +static void zend_compile_binding_pattern(zend_ast **ast_ptr) +{ + zend_ast *binding_pattern_ast = *ast_ptr; + zend_ast *var_name_ast = binding_pattern_ast->child[0]; + zend_string *var_name = zend_ast_get_str(var_name_ast); + uint32_t var = lookup_cv(var_name); + + zend_ast_destroy(var_name_ast); + binding_pattern_ast->child[0] = NULL; + binding_pattern_ast->attr = var; +} + +static void zend_compile_array_pattern(zend_ast **ast_ptr) +{ + zend_ast *array_pattern = *ast_ptr; + zend_ast_list *element_list = zend_ast_get_list(array_pattern->child[0]); + bool has_implicit = false, has_explicit = false; + + for (uint32_t i = 0; i < element_list->children; i++) { + zend_ast *element = element_list->child[i]; + zend_ast *key_ast = element->child[0]; + if (key_ast) { + has_explicit = true; + zval *key = zend_ast_get_zval(key_ast); + if (Z_TYPE_P(key) == IS_STRING) { + zend_ulong index; + if (ZEND_HANDLE_NUMERIC(Z_STR_P(key), index)) { + zval_ptr_dtor(key); + ZVAL_LONG(key, index); + } + } + } else { + has_implicit = true; + } + } + if (has_implicit && has_explicit) { + zend_throw_exception(zend_ce_compile_error, "Must not mix implicit and explicit array keys in array pattern", 0); + } +} + +static void verify_parenthesized_compound_pattern(zend_ast **ast_ptr, zend_ast_kind kind) +{ + zend_ast *ast = *ast_ptr; + zend_ast *lhs = ast->child[0]; + zend_ast *rhs = ast->child[1]; + if ((lhs->kind == kind && !(lhs->attr & ZEND_PARENTHESIZED_PATTERN)) + || (rhs->kind == kind && !(rhs->attr & ZEND_PARENTHESIZED_PATTERN))) { + zend_throw_exception(zend_ce_compile_error, "Nested compound pattern must be parenthesized", 0); + } +} + +static void zend_compile_or_pattern(zend_ast **ast_ptr) +{ + verify_parenthesized_compound_pattern(ast_ptr, ZEND_AST_AND_PATTERN); +} + +static void zend_compile_and_pattern(zend_ast **ast_ptr) +{ + verify_parenthesized_compound_pattern(ast_ptr, ZEND_AST_OR_PATTERN); +} + +struct zend_compile_pattern_context { + bool inside_or_pattern; +}; + +static void zend_compile_pattern(zend_ast **ast_ptr, void *context) +{ + zend_ast *ast = *ast_ptr; + if (ast == NULL || ast->kind == ZEND_AST_ZVAL) { + return; + } + + struct zend_compile_pattern_context *pattern_context = context; + struct zend_compile_pattern_context tmp_context = {0}; + if (!pattern_context) { + pattern_context = &tmp_context; + } + bool prev_inside_or_pattern = pattern_context->inside_or_pattern; + + switch (ast->kind) { + case ZEND_AST_OBJECT_PATTERN: + zend_compile_object_pattern(ast_ptr); + break; + case ZEND_AST_TYPE_PATTERN: + zend_compile_type_pattern(ast_ptr); + break; + case ZEND_AST_BINDING_PATTERN: + if (pattern_context->inside_or_pattern) { + zend_throw_exception(zend_ce_compile_error, "Must not bind to variables inside | pattern", 0); + } + zend_compile_binding_pattern(ast_ptr); + break; + case ZEND_AST_ARRAY_PATTERN: + zend_compile_array_pattern(ast_ptr); + break; + case ZEND_AST_CLASS_CONST_PATTERN: + zend_compile_class_const_pattern(ast_ptr); + break; + case ZEND_AST_OR_PATTERN: + pattern_context->inside_or_pattern = true; + zend_compile_or_pattern(ast_ptr); + break; + case ZEND_AST_AND_PATTERN: + zend_compile_and_pattern(ast_ptr); + break; + } + + zend_ast_apply(ast, zend_compile_pattern, pattern_context); + pattern_context->inside_or_pattern = prev_inside_or_pattern; +} + +static void zend_compile_is(znode *result, zend_ast *ast) +{ + zend_ast *expr_ast = ast->child[0]; + zend_ast **pattern_ast_ptr = &ast->child[1]; + + znode expr_node; + zend_compile_expr(&expr_node, expr_ast); + + zend_compile_pattern(pattern_ast_ptr, NULL); + zval pattern_zv; + ZVAL_AST(&pattern_zv, zend_ast_copy(*pattern_ast_ptr)); + zend_ast_destroy(*pattern_ast_ptr); + *pattern_ast_ptr = zend_ast_create_zval(&pattern_zv); + + znode pattern_node; + pattern_node.op_type = IS_CONST; + ZVAL_COPY(&pattern_node.u.constant, &pattern_zv); + + zend_emit_op_tmp(result, ZEND_IS, &expr_node, &pattern_node); + if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) { + // FIXME: Verify live ranges recognizes that OP1 needs to be freed if an exception occurs + zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); + } +} + static void zend_compile_try(zend_ast *ast) /* {{{ */ { zend_ast *try_ast = ast->child[0]; @@ -11606,6 +11838,9 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */ case ZEND_AST_MATCH: zend_compile_match(result, ast); return; + case ZEND_AST_IS: + zend_compile_is(result, ast); + return; default: ZEND_ASSERT(0 /* not supported */); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 63572ab6623cc..a819c97c39901 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1101,6 +1101,8 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); #define ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS 1 +#define ZEND_AST_RANGE_INCLUSIVE_END 1 + /* The send mode, the is_variadic, the is_promoted, and the is_tentative flags are stored as part of zend_type */ #define _ZEND_SEND_MODE_SHIFT _ZEND_TYPE_EXTRA_FLAGS_SHIFT #define _ZEND_IS_VARIADIC_BIT (1 << (_ZEND_TYPE_EXTRA_FLAGS_SHIFT + 2)) @@ -1127,6 +1129,9 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); #define IS_CONSTANT_CLASS 0x400 /* __CLASS__ in trait */ #define IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE 0x800 +/* Array pattern contains ... */ +#define ZEND_ARRAY_PATTERN_NON_EXHAUSTIVE 1 + static zend_always_inline bool zend_check_arg_send_type(const zend_function *zf, uint32_t arg_num, uint32_t mask) { arg_num--; @@ -1195,6 +1200,8 @@ static zend_always_inline bool zend_check_arg_send_type(const zend_function *zf, /* Used to distinguish (parent::$prop)::get() from parent hook call. */ #define ZEND_PARENTHESIZED_STATIC_PROP 1 +#define ZEND_PARENTHESIZED_PATTERN 1 + /* For "use" AST nodes and the seen symbol table */ #define ZEND_SYMBOL_CLASS (1<<0) #define ZEND_SYMBOL_FUNCTION (1<<1) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 44021b785ba95..f4926275dafb4 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -44,6 +44,7 @@ #include "zend_system_id.h" #include "zend_call_stack.h" #include "zend_attributes.h" +#include "zend_pattern_matching.h" #include "Optimizer/zend_func_info.h" /* Virtual current working directory support */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 8b3d2618112ba..0a9810baf2c90 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -39,6 +39,7 @@ #include "zend_observer.h" #include "zend_call_stack.h" #include "zend_frameless_function.h" +#include "zend_pattern_matching.h" #ifdef HAVE_SYS_TIME_H #include #endif @@ -205,6 +206,8 @@ void init_executor(void) /* {{{ */ zend_fiber_init(); zend_weakrefs_init(); + zend_pm_contexts_free(); + EG(active) = 1; } /* }}} */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 62a97d753634a..9d4163517a72e 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -43,6 +43,7 @@ #include "zend_max_execution_timer.h" #include "zend_strtod.h" #include "zend_lazy_objects.h" +#include "zend_pattern_matching.h" /* Define ZTS if you want a thread-safe Zend */ /*#undef ZTS*/ @@ -313,6 +314,8 @@ struct _zend_executor_globals { #endif zend_strtod_state strtod_state; + zend_pm_context *pm_context; + zend_pm_context pm_context_spare; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index d2a29e670d8bf..ed876a65ee766 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -52,6 +52,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %destructor { if ($$) zend_string_release_ex($$, 0); } %precedence T_THROW +%precedence T_IS %precedence PREC_ARROW_FUNCTION %precedence T_INCLUDE T_INCLUDE_ONCE T_REQUIRE T_REQUIRE_ONCE %left T_LOGICAL_OR @@ -134,6 +135,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_CASE "'case'" %token T_DEFAULT "'default'" %token T_MATCH "'match'" +%token T_IS "'is'" %token T_BREAK "'break'" %token T_CONTINUE "'continue'" %token T_GOTO "'goto'" @@ -236,6 +238,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_COALESCE "'??'" %token T_POW "'**'" %token T_POW_EQUAL "'**='" +%token T_RANGE_EXCLUSIVE_END "'..<'" +%token T_RANGE_INCLUSIVE_END "'..='" /* We need to split the & token in two to avoid a shift/reduce conflict. For T1&$v and T1&T2, * with only one token lookahead, bison does not know whether to reduce T1 as a complete type, * or shift to continue parsing an intersection type. */ @@ -280,11 +284,15 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type inline_function union_type_element union_type intersection_type %type attributed_statement attributed_class_statement attributed_parameter %type attribute_decl attribute attributes attribute_group namespace_declaration_name -%type match match_arm_list non_empty_match_arm_list match_arm match_arm_cond_list +%type match match_arm_list non_empty_match_arm_list match_arm match_arm_cond_list match_arm_cond %type enum_declaration_statement enum_backing_type enum_case enum_case_expr %type function_name non_empty_member_modifiers %type property_hook property_hook_list optional_property_hook_list hooked_property property_hook_body %type optional_parameter_list +%type pattern atomic_pattern compound_pattern type_pattern scalar_pattern or_pattern and_pattern class_const_pattern +%type object_pattern object_pattern_element_list non_empty_object_pattern_element_list +%type object_pattern_element range_pattern binding_pattern +%type array_pattern array_pattern_element_list array_pattern_element %type returns_ref function fn is_reference is_variadic property_modifiers property_hook_modifiers %type method_modifiers class_const_modifiers member_modifier optional_cpp_modifiers @@ -309,7 +317,7 @@ reserved_non_modifiers: | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_FN | T_MATCH | T_ENUM - | T_PROPERTY_C + | T_PROPERTY_C | T_IS ; semi_reserved: @@ -574,6 +582,11 @@ function_name: if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } $$ = zend_ast_create_zval(&zv); } + | T_IS { + zval zv; + if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } + $$ = zend_ast_create_zval(&zv); + } ; function_declaration_statement: @@ -740,8 +753,13 @@ match_arm: ; match_arm_cond_list: - expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } - | match_arm_cond_list ',' expr { $$ = zend_ast_list_add($1, $3); } + match_arm_cond { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } + | match_arm_cond_list ',' match_arm_cond { $$ = zend_ast_list_add($1, $3); } +; + +match_arm_cond: + expr { $$ = $1; } + | T_IS pattern { $$ = zend_ast_create(ZEND_AST_IS, NULL, $2); } ; @@ -1330,8 +1348,123 @@ expr: | attributes T_STATIC inline_function { $$ = zend_ast_with_attributes($3, $1); ((zend_ast_decl *) $$)->flags |= ZEND_ACC_STATIC; } | match { $$ = $1; } + | expr T_IS pattern { $$ = zend_ast_create(ZEND_AST_IS, $1, $3); } +; + +pattern: + atomic_pattern { $$ = $1; } + | compound_pattern { $$ = $1; } +; + +atomic_pattern: + scalar_pattern { $$ = $1; } + | type_pattern { $$ = $1; } + | object_pattern { $$ = $1; } + | range_pattern { $$ = $1; } + | array_pattern { $$ = $1; } + | binding_pattern { $$ = $1; } + | class_const_pattern { $$ = $1; } + | '*' { $$ = zend_ast_create(ZEND_AST_WILDCARD_PATTERN); } + | '(' pattern ')' { + $$ = $2; + if ($$->kind == ZEND_AST_OR_PATTERN || $$->kind == ZEND_AST_AND_PATTERN) { + $$->attr = ZEND_PARENTHESIZED_CONDITIONAL; + } + } +; + +compound_pattern: + or_pattern { $$ = $1; } + | and_pattern { $$ = $1; } +; + +type_pattern: + type_without_static { $$ = zend_ast_create(ZEND_AST_TYPE_PATTERN, $1); } + | '?' type_without_static { $$ = zend_ast_create(ZEND_AST_TYPE_PATTERN, $2); $2->attr |= ZEND_TYPE_NULLABLE; } +; + +scalar_pattern: + T_LNUMBER { $$ = $1; } + | T_DNUMBER { $$ = $1; } + | T_CONSTANT_ENCAPSED_STRING { $$ = $1; } + | '"' '"' { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); } + | '"' T_ENCAPSED_AND_WHITESPACE '"' { $$ = $2; } + | T_START_HEREDOC T_END_HEREDOC { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); } + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; } +; + +object_pattern: + class_name '{' object_pattern_element_list '}' { $$ = zend_ast_create(ZEND_AST_OBJECT_PATTERN, $1, $3); } +; + +object_pattern_element_list: + %empty { $$ = zend_ast_create_list(0, ZEND_AST_OBJECT_PATTERN_ELEMENT_LIST); } + | non_empty_object_pattern_element_list { $$ = $1; } + | non_empty_object_pattern_element_list ',' { $$ = $1; } ; +non_empty_object_pattern_element_list: + object_pattern_element { $$ = zend_ast_create_list(1, ZEND_AST_OBJECT_PATTERN_ELEMENT_LIST, $1); } + | non_empty_object_pattern_element_list ',' object_pattern_element { $$ = zend_ast_list_add($1, $3); } +; + +object_pattern_element: + T_STRING ':' pattern { $$ = zend_ast_create(ZEND_AST_OBJECT_PATTERN_ELEMENT, $1, $3); } + | binding_pattern { + zend_string *name = zend_string_copy(zend_ast_get_str($1->child[0])); + $$ = zend_ast_create(ZEND_AST_OBJECT_PATTERN_ELEMENT, zend_ast_create_zval_from_str(name), $1); + } +; + +or_pattern: + pattern '|' pattern { $$ = zend_ast_create(ZEND_AST_OR_PATTERN, $1, $3); } +; + +and_pattern: + pattern T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG pattern { $$ = zend_ast_create(ZEND_AST_AND_PATTERN, $1, $3); } + | pattern T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG pattern { $$ = zend_ast_create(ZEND_AST_AND_PATTERN, $1, $3); } +; + +range_pattern: + scalar_pattern T_RANGE_EXCLUSIVE_END scalar_pattern { $$ = zend_ast_create(ZEND_AST_RANGE_PATTERN, $1, $3); } + | scalar_pattern T_RANGE_INCLUSIVE_END scalar_pattern + { $$ = zend_ast_create(ZEND_AST_RANGE_PATTERN, $1, $3); $$->attr = ZEND_AST_RANGE_INCLUSIVE_END; } +; + +binding_pattern: + T_VARIABLE { $$ = zend_ast_create(ZEND_AST_BINDING_PATTERN, $1, NULL); } + | T_VARIABLE '@' pattern { $$ = zend_ast_create(ZEND_AST_BINDING_PATTERN, $1, $3); } +; + +array_pattern: + '[' ']' { $$ = zend_ast_create(ZEND_AST_ARRAY_PATTERN, zend_ast_create_list(0, ZEND_AST_ARRAY_PATTERN_ELEMENT_LIST)); } + | '[' T_ELLIPSIS ']' { + $$ = zend_ast_create_ex( + ZEND_AST_ARRAY_PATTERN, + ZEND_ARRAY_PATTERN_NON_EXHAUSTIVE, + zend_ast_create_list(0, ZEND_AST_ARRAY_PATTERN_ELEMENT_LIST)); + } + | '[' array_pattern_element_list possible_comma ']' { $$ = zend_ast_create(ZEND_AST_ARRAY_PATTERN, $2); } + | '[' array_pattern_element_list ',' T_ELLIPSIS ']' { + $$ = zend_ast_create_ex(ZEND_AST_ARRAY_PATTERN, ZEND_ARRAY_PATTERN_NON_EXHAUSTIVE, $2); + } +; + +array_pattern_element_list: + array_pattern_element { $$ = zend_ast_create_list(1, ZEND_AST_ARRAY_PATTERN_ELEMENT_LIST, $1); } + | array_pattern_element_list ',' array_pattern_element { $$ = zend_ast_list_add($1, $3); } +; + +array_pattern_element: + pattern { $$ = zend_ast_create(ZEND_AST_ARRAY_PATTERN_ELEMENT, NULL, $1); } + | scalar_pattern T_DOUBLE_ARROW pattern + { $$ = zend_ast_create(ZEND_AST_ARRAY_PATTERN_ELEMENT, $1, $3); } +; + +class_const_pattern: + class_name T_PAAMAYIM_NEKUDOTAYIM identifier + { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_PATTERN, $1, $3); } +; inline_function: function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 7ae73875926eb..9473f5755af08 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -1505,6 +1505,10 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN_WITH_IDENT(T_MATCH); } +"is" { + RETURN_TOKEN_WITH_IDENT(T_IS); +} + "endswitch" { RETURN_TOKEN_WITH_IDENT(T_ENDSWITCH); } @@ -1605,6 +1609,14 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN(T_ELLIPSIS); } +"..<" { + RETURN_TOKEN(T_RANGE_EXCLUSIVE_END); +} + +"..=" { + RETURN_TOKEN(T_RANGE_INCLUSIVE_END); +} + "??" { RETURN_TOKEN(T_COALESCE); } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 12c2759656b2d..28d9c6712fb5a 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -898,7 +898,8 @@ static bool keeps_op1_alive(zend_op *opline) { || opline->opcode == ZEND_MATCH_ERROR || opline->opcode == ZEND_FETCH_LIST_R || opline->opcode == ZEND_FETCH_LIST_W - || opline->opcode == ZEND_COPY_TMP) { + || opline->opcode == ZEND_COPY_TMP + || opline->opcode == ZEND_IS) { return 1; } ZEND_ASSERT(opline->opcode != ZEND_FE_FETCH_R diff --git a/Zend/zend_pattern_matching.c b/Zend/zend_pattern_matching.c new file mode 100644 index 0000000000000..5ae980ba5b959 --- /dev/null +++ b/Zend/zend_pattern_matching.c @@ -0,0 +1,370 @@ +/* + +----------------------------------------------------------------------+ + | 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. | + +----------------------------------------------------------------------+ +*/ + +#include "zend_pattern_matching.h" +#include "zend_API.h" +#include "zend_compile.h" +#include "zend_execute.h" +#include "zend_exceptions.h" +#include "zend_type_info.h" +#include "zend_constants.h" + +typedef enum { + PM_ERROR = -1, + PM_MISMATCH = 0, + PM_MATCH = 1, +} pm_result; + +pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern); + +static pm_result match_type(zval *zv, zend_ast *type_ast) +{ + zend_ast *class_name_ast = type_ast->child[0]; + if (class_name_ast) { + if (Z_TYPE_P(zv) != IS_OBJECT) { + return PM_MISMATCH; + } + + zend_object *obj = Z_OBJ_P(zv); + zend_string *class_name = zend_ast_get_str(class_name_ast); + if (!zend_string_equals_ci(obj->ce->name, class_name)) { + zend_class_entry *expected_class = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (!expected_class || !instanceof_function(Z_OBJ_P(zv)->ce, expected_class)) { + return PM_MISMATCH; + } + } + } else { + zend_type type = ZEND_TYPE_INIT_MASK(type_ast->attr); + if (!ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(zv))) { + return PM_MISMATCH; + } + } + + return PM_MATCH; +} + +static bool match_zval(zval *lhs, zval *rhs) +{ + return zend_is_identical(lhs, rhs); +} + +static zend_class_entry *get_class_from_fetch_type(uint32_t fetch_type) +{ + zend_class_entry *scope; + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + scope = zend_get_executed_scope(); + if (UNEXPECTED(!scope)) { + zend_throw_error(NULL, "%s", "Cannot access \"self\" when no class scope is active"); + return NULL; + } + return scope; + case ZEND_FETCH_CLASS_PARENT: + scope = zend_get_executed_scope(); + if (UNEXPECTED(!scope)) { + zend_throw_error(NULL, "%s", "Cannot access \"parent\" when no class scope is active"); + return NULL; + } + scope = scope->parent; + if (UNEXPECTED(!scope)) { + zend_throw_error(NULL, "%s", "Cannot access \"parent\" when current class scope has no parent"); + return NULL; + } + return scope; + case ZEND_FETCH_CLASS_STATIC: + scope = zend_get_called_scope(EG(current_execute_data)); + if (UNEXPECTED(!scope)) { + zend_throw_error(NULL, "%s", "Cannot access \"static\" when no class scope is active"); + return NULL; + } + return scope; + EMPTY_SWITCH_DEFAULT_CASE(); + } + + return NULL; +} + +static pm_result match_object(zval *zv, zend_ast *pattern) +{ + if (Z_TYPE_P(zv) != IS_OBJECT) { + return PM_MISMATCH; + } + + zend_object *obj = Z_OBJ_P(zv); + zend_ast *class_name_ast = pattern->child[0]; + + if (class_name_ast) { + zend_string *class_name = zend_ast_get_str(class_name_ast); + if (!zend_string_equals_ci(obj->ce->name, class_name)) { + zend_class_entry *expected_class = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (!expected_class || !instanceof_function(Z_OBJ_P(zv)->ce, expected_class)) { + return PM_MISMATCH; + } + } + } else { + uint32_t fetch_type = pattern->attr; + zend_class_entry *scope = get_class_from_fetch_type(fetch_type); + if (EG(exception)) { + return PM_ERROR; + } + if (!instanceof_function(Z_OBJ_P(zv)->ce, scope)) { + return PM_MISMATCH; + } + } + + zend_ast_list *elements = zend_ast_get_list(pattern->child[1]); + for (uint32_t i = 0; i < elements->children; i++) { + zend_ast *element = elements->child[i]; + zend_ast *property_or_method_call = element->child[0]; + zend_ast *element_pattern = element->child[1]; + zend_string *property_name = zend_ast_get_str(property_or_method_call); + zval property_result_rv; + zval *property_result = obj->handlers->read_property(obj, property_name, BP_VAR_R, NULL, &property_result_rv); + pm_result element_matched = zend_pattern_match_ex(property_result, element_pattern); + if (property_result == &property_result_rv) { + zval_ptr_dtor(property_result); + } + if (element_matched != PM_MATCH) { + return element_matched; + } + } + + return PM_MATCH; +} + +static pm_result match_range(zval *zv, zend_ast *pattern) +{ + zval *start = zend_ast_get_zval(pattern->child[0]); + zval *end = zend_ast_get_zval(pattern->child[1]); + + if (Z_TYPE_P(zv) != Z_TYPE_P(start) && zend_compare(zv, start) == -1) { + return PM_MISMATCH; + } + + int end_check = zend_compare(zv, end); + if (Z_TYPE_P(zv) != Z_TYPE_P(end) || end_check == 1 || (!(pattern->attr & ZEND_AST_RANGE_INCLUSIVE_END) && end_check == 0)) { + return PM_MISMATCH; + } + + return PM_MATCH; +} + +static pm_result match_binding(zval *zv, zend_ast *pattern) +{ + zend_ast *sub_pattern = pattern->child[1]; + if (sub_pattern && !zend_pattern_match_ex(zv, sub_pattern)) { + return PM_MISMATCH; + } + + zend_pm_context *context = EG(pm_context); + zend_pm_bindings *bindings = context->bindings; + if (!bindings) { + bindings = &context->bindings_spare; + context->bindings = bindings; + context->last_bindings = bindings; + } else if (bindings->num_used == ZEND_PM_BINDINGS_SLOTS) { + zend_pm_bindings *new_bindings = emalloc(sizeof(zend_pm_bindings)); + new_bindings->num_used = 0; + new_bindings->next = NULL; + context->last_bindings->next = new_bindings; + context->last_bindings = new_bindings; + bindings = new_bindings; + } + + zend_pm_binding *binding = &bindings->list[bindings->num_used++]; + binding->var = (uint32_t) pattern->attr; + ZVAL_COPY(&binding->value, zv); + + return PM_MATCH; +} + +static pm_result match_array(zval *zv, zend_ast *pattern) +{ + if (Z_TYPE_P(zv) != IS_ARRAY) { + return PM_MISMATCH; + } + + HashTable *ht = Z_ARRVAL_P(zv); + zend_ast_list *element_list = zend_ast_get_list(pattern->child[0]); + + if (pattern->attr & ZEND_ARRAY_PATTERN_NON_EXHAUSTIVE) { + if (element_list->children > zend_hash_num_elements(ht)) { + return PM_MISMATCH; + } + } else { + if (element_list->children != zend_hash_num_elements(ht)) { + return PM_MISMATCH; + } + } + + /* Explicit and implicit keys may not be mixed, so there's no need to + * replicate array key sequencing logic. */ + zend_long index = 0; + + for (uint32_t i = 0; i < element_list->children; i++) { + zend_ast *element = element_list->child[i]; + zend_ast *key_ast = element->child[0]; + zend_ast *pattern_ast = element->child[1]; + zval *element_zv; + if (key_ast) { + zval *key_zv = zend_ast_get_zval(key_ast); + if (Z_TYPE_P(key_zv) == IS_LONG) { + element_zv = zend_hash_index_find(ht, Z_LVAL_P(key_zv)); + } else { + ZEND_ASSERT(Z_TYPE_P(key_zv) == IS_STRING); + element_zv = zend_hash_find(ht, Z_STR_P(key_zv)); + } + } else { + element_zv = zend_hash_index_find(ht, index); + index++; + } + if (!element_zv || Z_TYPE_P(element_zv) == IS_UNDEF || !zend_pattern_match_ex(element_zv, pattern_ast)) { + return PM_MISMATCH; + } + } + + return PM_MATCH; +} + +pm_result match_class_const(zval *zv, zend_ast *pattern) +{ + zend_string *class_name = !pattern->attr + ? zend_ast_get_str(pattern->child[0]) + : NULL; + zend_string *constant_name = zend_ast_get_str(pattern->child[1]); + zval *constant_zv = zend_get_class_constant_ex(class_name, constant_name, zend_get_executed_scope(), pattern->attr); + if (EG(exception)) { + return PM_ERROR; + } + return zend_is_identical(zv, constant_zv) ? PM_MATCH : PM_MISMATCH; +} + +pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern) +{ + ZVAL_DEREF(zv); + + switch (pattern->kind) { + case ZEND_AST_TYPE_PATTERN: + return match_type(zv, pattern); + case ZEND_AST_ZVAL: + return match_zval(zv, zend_ast_get_zval(pattern)); + case ZEND_AST_OBJECT_PATTERN: + return match_object(zv, pattern); + case ZEND_AST_WILDCARD_PATTERN: + return PM_MATCH; + case ZEND_AST_OR_PATTERN: { + pm_result lhs = zend_pattern_match_ex(zv, pattern->child[0]); + if (lhs != PM_MISMATCH) { + return lhs; + } + return zend_pattern_match_ex(zv, pattern->child[1]); + } + case ZEND_AST_AND_PATTERN: { + pm_result lhs = zend_pattern_match_ex(zv, pattern->child[0]); + if (lhs != PM_MATCH) { + return lhs; + } + return zend_pattern_match_ex(zv, pattern->child[1]); + } + case ZEND_AST_RANGE_PATTERN: + return match_range(zv, pattern); + case ZEND_AST_BINDING_PATTERN: + return match_binding(zv, pattern); + case ZEND_AST_ARRAY_PATTERN: + return match_array(zv, pattern); + case ZEND_AST_CLASS_CONST_PATTERN: + return match_class_const(zv, pattern); + EMPTY_SWITCH_DEFAULT_CASE(); + } +} + +static void create_context(void) +{ + if (!EG(pm_context)) { + EG(pm_context) = &EG(pm_context_spare); + } else { + zend_pm_context *prev = EG(pm_context); + EG(pm_context) = emalloc(sizeof(zend_pm_context)); + EG(pm_context)->prev = prev; + } +} + +static void pm_context_free(bool free_values) +{ + zend_pm_context *context = EG(pm_context); + zend_pm_bindings *bindings = context->bindings; + + EG(pm_context) = context->prev; + + while (bindings) { + if (free_values) { + for (uint8_t i = 0; i < bindings->num_used; i++) { + zval_ptr_dtor(&bindings->list[i].value); + } + } + zend_pm_bindings *next = bindings->next; + if (bindings != &context->bindings_spare) { + efree(bindings); + } + bindings = next; + } + + context->bindings = NULL; + memset(&context->bindings_spare, 0, sizeof(context->bindings_spare)); + + if (context != &EG(pm_context_spare)) { + efree(context); + } else { + memset(context, 0, sizeof(zend_pm_context)); + } +} + +static void bind_variables(void) +{ + zend_pm_context *context = EG(pm_context); + zend_pm_bindings *bindings = context->bindings; + zend_execute_data *execute_data = EG(current_execute_data); + while (bindings) { + for (uint32_t i = 0; i < bindings->num_used; i++) { + zend_pm_binding *binding = &bindings->list[i]; + zend_assign_to_variable(EX_VAR(binding->var), &binding->value, IS_CV, EX_USES_STRICT_TYPES()); + } + bindings = bindings->next; + } +} + +void zend_pm_contexts_free(void) +{ + while (EG(pm_context)) { + pm_context_free(false); + } +} + +bool zend_pattern_match(zval *zv, zend_ast *pattern) +{ + // FIXME: Only create context when necessary + create_context(); + pm_result result = zend_pattern_match_ex(zv, pattern); + if (result == PM_MATCH) { + bind_variables(); + pm_context_free(true); + return true; + } else { + pm_context_free(true); + return false; + } +} diff --git a/Zend/zend_pattern_matching.h b/Zend/zend_pattern_matching.h new file mode 100644 index 0000000000000..673c947d1f416 --- /dev/null +++ b/Zend/zend_pattern_matching.h @@ -0,0 +1,47 @@ +/* + +----------------------------------------------------------------------+ + | 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. | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_PATTERN_MATCHING_H +#define ZEND_PATTERN_MATCHING_H + +#include "zend.h" + +#define ZEND_PM_BINDINGS_SLOTS 8 + +typedef struct { + uint32_t var; + zval value; +} zend_pm_binding; + +typedef struct _zend_pm_bindings zend_pm_bindings; +struct _zend_pm_bindings { + zend_pm_binding list[ZEND_PM_BINDINGS_SLOTS]; + zend_pm_bindings *next; + uint8_t num_used; +}; + +typedef struct _zend_pm_context zend_pm_context; +typedef struct _zend_pm_context { + zend_pm_bindings *bindings; + zend_pm_bindings *last_bindings; + zend_pm_bindings bindings_spare; + zend_pm_context *prev; +} zend_pm_context; + +bool zend_pattern_match(zval *zv, zend_ast *pattern); +void zend_pm_contexts_free(void); + +#endif diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7e471b5acd8b6..be00302c6464d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9299,6 +9299,17 @@ ZEND_VM_C_LABEL(default_branch): } } +ZEND_VM_HANDLER(210, ZEND_IS, ANY, CONST) +{ + USE_OPLINE + SAVE_OPLINE(); + zval *expr = GET_OP1_ZVAL_PTR(BP_VAR_R); + zval *pattern = GET_OP2_ZVAL_PTR(BP_VAR_R); + bool result = zend_pattern_match(expr, Z_ASTVAL_P(pattern)); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + ZEND_VM_COLD_CONST_HANDLER(197, ZEND_MATCH_ERROR, CONST|TMPVARCV, UNUSED) { USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9209399a5cdbf..f4681963b043a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4117,6 +4117,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + zval *expr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + zval *pattern = RT_CONSTANT(opline, opline->op2); + bool result = zend_pattern_match(expr, Z_ASTVAL_P(pattern)); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -57643,6 +57654,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_LABEL, (void*)&&ZEND_JMP_FRAMELESS_SPEC_CONST_LABEL, (void*)&&ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_LABEL, + (void*)&&ZEND_IS_SPEC_CONST_LABEL, (void*)&&ZEND_INIT_FCALL_OFFSET_SPEC_CONST_LABEL, (void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -59045,6 +59057,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_RECV_INIT_SPEC_CONST) HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_SPEC_CONST): + VM_TRACE(ZEND_IS_SPEC_CONST) + ZEND_IS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_IS_SPEC_CONST) + HYBRID_BREAK(); HYBRID_CASE(ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR): VM_TRACE(ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR) ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -66830,6 +66847,7 @@ void zend_vm_init(void) ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_HANDLER, ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER, + ZEND_IS_SPEC_CONST_HANDLER, ZEND_INIT_FCALL_OFFSET_SPEC_CONST_HANDLER, ZEND_RECV_NOTYPE_SPEC_HANDLER, ZEND_NULL_HANDLER, @@ -67787,7 +67805,7 @@ void zend_vm_init(void) 1255, 1256 | SPEC_RULE_OP1, 1261 | SPEC_RULE_OP1, - 3486, + 3487, 1266 | SPEC_RULE_OP1, 1271 | SPEC_RULE_OP1, 1276 | SPEC_RULE_OP2, @@ -67821,7 +67839,7 @@ void zend_vm_init(void) 1559 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1584 | SPEC_RULE_OP1, 1589, - 3486, + 3487, 1590 | SPEC_RULE_OP1, 1595 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1620 | SPEC_RULE_OP1 | SPEC_RULE_OP2, @@ -67952,52 +67970,52 @@ void zend_vm_init(void) 2573 | SPEC_RULE_OBSERVER, 2575, 2576, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, + 2577, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, }; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) zend_opcode_handler_funcs = labels; @@ -68170,7 +68188,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 = 2585 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2586 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -68178,7 +68196,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 = 2610 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2611 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -68186,7 +68204,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 = 2635 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2636 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -68197,17 +68215,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 = 2660 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2661 | 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 = 2685 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2686 | 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 = 2710 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2711 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -68218,17 +68236,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 = 2735 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2736 | 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 = 2760 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2761 | 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 = 2785 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2786 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_IDENTICAL: @@ -68239,14 +68257,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 = 2810 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2811 | 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 = 2885 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2886 | 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 = 3110 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3111 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_IDENTICAL: @@ -68257,14 +68275,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 = 2960 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2961 | 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 = 3035 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3036 | 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 = 3115 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3116 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_EQUAL: @@ -68275,12 +68293,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 = 2810 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2811 | 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 = 2885 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2886 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_EQUAL: @@ -68291,12 +68309,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 = 2960 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2961 | 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 = 3035 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3036 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_SMALLER: @@ -68304,12 +68322,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 = 3120 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3121 | 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 = 3195 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3196 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -68317,79 +68335,79 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3270 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3271 | 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 = 3345 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3346 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if (op1_info == MAY_BE_LONG) { - spec = 3432 | SPEC_RULE_OP1; + spec = 3433 | SPEC_RULE_OP1; } else if (op1_info == MAY_BE_DOUBLE) { - spec = 3437 | SPEC_RULE_OP1; + spec = 3438 | 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 = 3442 | SPEC_RULE_OP1; + spec = 3443 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3420 | SPEC_RULE_RETVAL; + spec = 3421 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3422 | SPEC_RULE_RETVAL; + spec = 3423 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3424 | SPEC_RULE_RETVAL; + spec = 3425 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3426 | SPEC_RULE_RETVAL; + spec = 3427 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3428; - } else if (op1_info == MAY_BE_LONG) { spec = 3429; + } else if (op1_info == MAY_BE_LONG) { + spec = 3430; } break; case ZEND_POST_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3430; - } else if (op1_info == MAY_BE_LONG) { spec = 3431; + } else if (op1_info == MAY_BE_LONG) { + spec = 3432; } break; case ZEND_JMP: if (OP_JMP_ADDR(op, op->op1) > op) { - spec = 2584; + spec = 2585; } break; case ZEND_INIT_FCALL: if (Z_EXTRA_P(RT_CONSTANT(op, op->op2)) != 0) { - spec = 2577; + spec = 2578; } break; case ZEND_RECV: if (op->op2.num == MAY_BE_ANY) { - spec = 2578; + spec = 2579; } 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 = 3482; + spec = 3483; } 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 = 3477 | SPEC_RULE_OP1; + spec = 3478 | 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 = 3484 | SPEC_RULE_RETVAL; + spec = 3485 | SPEC_RULE_RETVAL; } break; case ZEND_FETCH_DIM_R: @@ -68397,22 +68415,22 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3447 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3448 | 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 = 3483; + spec = 3484; } break; case ZEND_SEND_VAR: if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3472 | SPEC_RULE_OP1; + spec = 3473 | SPEC_RULE_OP1; } break; case ZEND_COUNT: if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 2579 | SPEC_RULE_OP1; + spec = 2580 | SPEC_RULE_OP1; } break; case ZEND_BW_OR: diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 7f3a3cb5de260..6472580efa999 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1372,502 +1372,503 @@ _(2574, ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER) \ _(2575, ZEND_JMP_FRAMELESS_SPEC_CONST) \ _(2576, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED) \ - _(2577, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \ - _(2578, ZEND_RECV_NOTYPE_SPEC) \ - _(2580, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ + _(2577, ZEND_IS_SPEC_CONST) \ + _(2578, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \ + _(2579, ZEND_RECV_NOTYPE_SPEC) \ _(2581, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ - _(2583, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ - _(2584, ZEND_JMP_FORWARD_SPEC) \ - _(2590, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2591, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2582, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ + _(2584, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ + _(2585, ZEND_JMP_FORWARD_SPEC) \ + _(2591, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2592, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2594, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2595, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2596, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2593, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2595, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2596, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2597, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2599, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2605, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2606, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2598, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2600, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2606, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2607, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2609, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2615, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2616, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2608, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2610, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2616, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2617, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2619, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2620, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2621, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2618, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2620, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2621, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2622, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2624, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2630, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2631, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2623, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2625, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2631, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2632, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2634, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2640, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2641, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2633, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2635, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2641, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2642, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2644, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2645, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2646, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2643, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2645, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2646, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2647, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2649, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2655, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2656, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2648, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2650, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2656, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2657, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2659, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2661, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2658, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2660, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2662, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2664, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2665, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2666, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2663, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2665, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2666, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2667, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2669, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2670, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2671, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2668, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2670, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2671, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2672, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2674, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2680, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2681, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2673, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2675, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2681, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2682, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2684, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2686, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2683, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2685, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2687, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2689, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2690, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2691, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2688, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2690, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2691, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2692, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2694, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2695, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2696, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2693, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2695, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2696, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2697, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2699, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2705, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2706, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2698, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2700, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2706, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2707, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2709, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2711, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2708, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2710, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2712, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2714, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2715, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2716, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2713, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2715, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2716, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2717, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2719, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2720, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2721, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2718, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2720, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2721, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2722, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2724, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2730, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2731, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2723, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2725, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2731, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2732, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2734, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2740, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2741, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2733, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2735, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2741, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2742, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2744, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2745, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2746, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2743, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2745, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2746, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2747, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2749, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2755, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2756, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2748, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2750, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2756, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2757, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2759, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2765, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2766, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2758, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2760, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2766, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2767, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2769, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2770, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2771, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2768, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2770, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2771, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2772, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2774, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2780, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2781, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2773, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2775, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2781, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2782, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2784, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2790, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2791, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2783, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2785, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2791, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2792, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2794, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2795, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2796, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2793, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2795, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2796, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2797, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2799, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2805, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2806, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2798, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2800, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2806, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2807, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2809, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2825, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2826, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2829, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2830, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2831, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2832, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2833, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2843, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2844, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2845, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2846, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2847, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2848, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2852, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2853, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2854, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2870, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2871, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2872, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2873, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2874, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2875, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2876, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2877, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2878, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2882, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2883, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2884, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2900, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2901, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2904, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2905, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2906, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2907, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2908, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2918, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2919, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2920, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2921, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2922, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2923, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2927, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2928, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2929, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2945, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2946, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2947, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2948, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2949, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2950, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2951, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2952, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2953, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2957, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2958, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2959, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2975, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2976, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2979, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2980, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2981, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2982, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2983, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2993, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2994, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2995, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2996, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2997, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2998, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3002, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3003, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3004, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3020, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3021, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3022, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3023, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3024, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3025, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3026, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3027, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3028, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3032, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3033, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3034, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3050, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3051, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3054, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3055, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3056, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3057, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3058, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3068, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3069, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3070, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3071, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3072, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3073, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3077, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3078, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3079, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3095, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3096, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3097, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3098, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3099, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3100, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3101, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3102, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3103, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3107, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3108, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3109, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3110, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3114, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3115, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3119, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3123, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3124, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3125, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3126, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3127, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3128, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3132, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3133, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3134, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3135, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3136, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3139, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3140, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3141, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3154, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3155, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3156, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3157, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3158, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3162, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3163, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3164, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3180, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3181, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3183, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3184, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3185, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3186, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3187, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3188, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3192, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3193, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3194, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3198, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3207, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3208, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3209, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3210, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3211, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3214, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3215, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3216, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3229, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3230, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3231, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3232, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3233, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3237, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3238, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3239, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3255, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3256, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3258, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3259, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3260, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3261, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3262, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3263, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3267, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3268, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3269, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3273, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3282, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3283, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3284, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3285, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3286, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3289, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3290, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3291, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3304, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3305, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3306, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3307, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3308, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3312, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3313, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3314, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3330, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3331, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3333, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3334, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3335, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3336, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3337, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3338, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3342, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3343, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3344, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3348, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3357, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3358, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3359, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3360, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3361, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3364, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3365, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3366, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3379, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3380, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3381, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3382, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3383, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3387, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3388, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3389, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3405, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3406, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3408, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3409, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3410, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3411, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3412, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3413, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3417, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3418, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3419, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3420, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3421, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3422, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3423, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ - _(3424, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3425, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3426, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3427, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ - _(3428, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3429, ZEND_POST_INC_LONG_SPEC_CV) \ - _(3430, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3431, ZEND_POST_DEC_LONG_SPEC_CV) \ - _(3432, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ - _(3433, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(2808, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2810, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2826, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2829, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2830, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2831, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2832, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2833, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2834, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2843, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2844, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2845, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2846, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2847, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2848, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2849, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2853, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2854, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2855, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2871, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2872, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2873, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2874, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2875, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2876, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2877, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2878, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2879, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2883, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2884, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2885, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2901, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2904, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2905, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2906, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2907, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2908, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2909, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2918, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2919, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2920, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2921, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2922, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2923, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2924, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2928, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2929, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2930, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2946, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2947, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2948, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2949, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2950, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2951, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2952, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2953, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2954, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2958, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2959, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2960, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2976, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2979, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2980, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2981, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2982, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2983, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2984, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2993, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2994, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2995, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2996, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2997, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2998, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2999, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3003, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3004, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3005, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3021, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3022, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3023, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3024, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3025, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3026, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3027, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3028, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3029, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3033, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3034, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3035, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3051, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3054, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3055, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3056, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3057, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3058, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3059, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3068, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3069, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3070, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3071, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3072, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3073, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3074, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3078, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3079, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3080, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3096, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3097, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3098, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3099, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3100, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3101, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3102, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3103, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3104, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3108, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3109, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3110, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3111, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3115, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3116, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3120, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3124, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3125, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3126, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3127, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3128, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3129, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3133, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3134, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3135, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3136, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3139, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3140, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3141, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3154, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3155, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3156, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3157, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3158, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3159, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3163, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3164, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3165, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3181, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3183, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3184, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3185, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3186, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3187, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3188, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3189, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3193, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3194, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3195, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3204, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3208, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3209, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3210, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3211, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3214, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3215, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3216, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3229, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3230, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3231, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3232, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3233, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3234, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3238, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3239, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3240, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3256, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3258, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3259, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3260, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3261, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3262, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3263, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3264, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3268, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3269, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3270, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3279, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3283, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3284, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3285, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3286, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3289, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3290, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3291, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3304, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3305, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3306, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3307, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3308, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3309, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3313, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3314, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3315, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3331, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3333, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3334, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3335, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3336, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3337, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3338, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3339, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3343, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3344, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3345, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3354, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3358, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3359, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3360, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3361, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3364, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3365, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3366, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3379, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3380, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3381, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3382, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3383, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3384, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3388, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3389, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3390, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3406, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3408, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3409, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3410, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3411, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3412, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3413, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3414, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3418, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3419, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3420, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3421, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3422, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3423, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3424, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ + _(3425, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3426, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3427, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3428, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ + _(3429, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3430, ZEND_POST_INC_LONG_SPEC_CV) \ + _(3431, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3432, ZEND_POST_DEC_LONG_SPEC_CV) \ + _(3433, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ _(3434, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3436, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3437, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ - _(3438, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3435, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3437, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3438, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ _(3439, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3441, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3442, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ - _(3443, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3440, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3442, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3443, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ _(3444, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3446, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3448, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3445, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3447, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ _(3449, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3451, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3452, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3453, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3450, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3452, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3453, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3454, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3456, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3457, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3458, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3455, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3457, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3458, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3459, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3461, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3467, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ - _(3468, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3460, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3462, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3468, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ _(3469, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3471, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3474, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ - _(3476, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ - _(3479, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ - _(3481, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ - _(3482, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ - _(3483, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ - _(3484, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ - _(3485, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ - _(3485+1, ZEND_NULL) + _(3470, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3472, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3475, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ + _(3477, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ + _(3480, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ + _(3482, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ + _(3483, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ + _(3484, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ + _(3485, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ + _(3486, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ + _(3486+1, ZEND_NULL) diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 202dfd3f734f3..66ea5c4e7afa1 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[210] = { +static const char *zend_vm_opcodes_names[211] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -233,9 +233,10 @@ static const char *zend_vm_opcodes_names[210] = { "ZEND_FRAMELESS_ICALL_3", "ZEND_JMP_FRAMELESS", "ZEND_INIT_PARENT_PROPERTY_HOOK_CALL", + "ZEND_IS", }; -static uint32_t zend_vm_opcodes_flags[210] = { +static uint32_t zend_vm_opcodes_flags[211] = { 0x00000000, 0x00000b0b, 0x00000b0b, @@ -446,6 +447,7 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x00000000, 0x01042003, 0x01001103, + 0x00000300, }; ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index d472b5b9660f5..e943207e56aa0 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -291,7 +291,8 @@ END_EXTERN_C() #define ZEND_FRAMELESS_ICALL_3 207 #define ZEND_JMP_FRAMELESS 208 #define ZEND_INIT_PARENT_PROPERTY_HOOK_CALL 209 +#define ZEND_IS 210 -#define ZEND_VM_LAST_OPCODE 209 +#define ZEND_VM_LAST_OPCODE 210 #endif diff --git a/configure.ac b/configure.ac index 01d9ded69b920..c68f19320bad8 100644 --- a/configure.ac +++ b/configure.ac @@ -1756,6 +1756,7 @@ PHP_ADD_SOURCES([Zend], m4_normalize([ zend_observer.c zend_opcode.c zend_operators.c + zend_pattern_matching.c zend_property_hooks.c zend_ptr_stack.c zend_signal.c diff --git a/ext/tokenizer/tokenizer_data.c b/ext/tokenizer/tokenizer_data.c index a046ab50e1498..19b412e5caa24 100644 --- a/ext/tokenizer/tokenizer_data.c +++ b/ext/tokenizer/tokenizer_data.c @@ -72,6 +72,7 @@ char *get_token_type_name(int token_type) case T_CASE: return "T_CASE"; case T_DEFAULT: return "T_DEFAULT"; case T_MATCH: return "T_MATCH"; + case T_IS: return "T_IS"; case T_BREAK: return "T_BREAK"; case T_CONTINUE: return "T_CONTINUE"; case T_GOTO: return "T_GOTO"; @@ -172,6 +173,8 @@ char *get_token_type_name(int token_type) case T_COALESCE: return "T_COALESCE"; case T_POW: return "T_POW"; case T_POW_EQUAL: return "T_POW_EQUAL"; + case T_RANGE_EXCLUSIVE_END: return "T_RANGE_EXCLUSIVE_END"; + case T_RANGE_INCLUSIVE_END: return "T_RANGE_INCLUSIVE_END"; case T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG: return "T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG"; case T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG: return "T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG"; case T_BAD_CHARACTER: return "T_BAD_CHARACTER"; diff --git a/ext/tokenizer/tokenizer_data.stub.php b/ext/tokenizer/tokenizer_data.stub.php index 45f3c89f2de3a..786f2aa9a9b6f 100644 --- a/ext/tokenizer/tokenizer_data.stub.php +++ b/ext/tokenizer/tokenizer_data.stub.php @@ -237,6 +237,11 @@ * @cvalue T_MATCH */ const T_MATCH = UNKNOWN; +/** + * @var int + * @cvalue T_IS + */ +const T_IS = UNKNOWN; /** * @var int * @cvalue T_BREAK @@ -737,6 +742,16 @@ * @cvalue T_POW_EQUAL */ const T_POW_EQUAL = UNKNOWN; +/** + * @var int + * @cvalue T_RANGE_EXCLUSIVE_END + */ +const T_RANGE_EXCLUSIVE_END = UNKNOWN; +/** + * @var int + * @cvalue T_RANGE_INCLUSIVE_END + */ +const T_RANGE_INCLUSIVE_END = UNKNOWN; /** * @var int * @cvalue T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG diff --git a/ext/tokenizer/tokenizer_data_arginfo.h b/ext/tokenizer/tokenizer_data_arginfo.h index 61f6ac1ec3659..99e61a67ac9bd 100644 --- a/ext/tokenizer/tokenizer_data_arginfo.h +++ b/ext/tokenizer/tokenizer_data_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d917cab61a2b436a16d2227cdb438add45e42d69 */ + * Stub hash: 4bc2a262c66d2b026380aa67a6d454ebc63ea05c */ static void register_tokenizer_data_symbols(int module_number) { @@ -50,6 +50,7 @@ static void register_tokenizer_data_symbols(int module_number) REGISTER_LONG_CONSTANT("T_CASE", T_CASE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_DEFAULT", T_DEFAULT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_MATCH", T_MATCH, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("T_IS", T_IS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_BREAK", T_BREAK, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_CONTINUE", T_CONTINUE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_GOTO", T_GOTO, CONST_PERSISTENT); @@ -150,6 +151,8 @@ static void register_tokenizer_data_symbols(int module_number) REGISTER_LONG_CONSTANT("T_COALESCE", T_COALESCE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_POW", T_POW, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_POW_EQUAL", T_POW_EQUAL, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("T_RANGE_EXCLUSIVE_END", T_RANGE_EXCLUSIVE_END, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("T_RANGE_INCLUSIVE_END", T_RANGE_INCLUSIVE_END, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG", T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG", T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_BAD_CHARACTER", T_BAD_CHARACTER, CONST_PERSISTENT); diff --git a/win32/build/config.w32 b/win32/build/config.w32 index 70e50891964b0..ab8a07ef8af40 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -241,7 +241,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.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_atomic.c zend_hrtime.c zend_frameless_function.c zend_property_hooks.c \ - zend_lazy_objects.c"); + zend_lazy_objects.c zend_pattern_matching.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 PHP_ASSEMBLER = PATH_PROG({ From ced9c19413d8e771bb07e3730b6f7ce13f93d92a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Jan 2025 17:41:08 +0100 Subject: [PATCH 2/5] Adjustments for upstream changes --- Zend/tests/pattern_matching/is/bail.phpt | 45 +++++++---------- Zend/tests/pattern_matching/is/binding.phpt | 4 +- Zend/tests/pattern_matching/is/object.phpt | 30 +++++------ Zend/zend_ast.h | 2 +- Zend/zend_compile.c | 41 +-------------- Zend/zend_language_parser.y | 15 +++--- Zend/zend_pattern_matching.c | 56 ++++++++++----------- 7 files changed, 70 insertions(+), 123 deletions(-) diff --git a/Zend/tests/pattern_matching/is/bail.phpt b/Zend/tests/pattern_matching/is/bail.phpt index 9e9437d10414b..033dca5218545 100644 --- a/Zend/tests/pattern_matching/is/bail.phpt +++ b/Zend/tests/pattern_matching/is/bail.phpt @@ -3,41 +3,30 @@ Object pattern matching --FILE-- getMessage(), "\n"; -} - -try { - var_dump($o is parent {}); -} catch (Throwable $e) { - echo $e->getMessage(), "\n"; -} - -try { - var_dump($o is static {}); -} catch (Throwable $e) { - echo $e->getMessage(), "\n"; -} + try { + var_dump($o is self); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + } -class C { - public static function test($o) { - try { - var_dump($o is parent {}); - } catch (Throwable $e) { - echo $e->getMessage(), "\n"; - } + try { + var_dump($o is parent); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; } -} -C::test($o); + try { + var_dump($o is static); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + } +})(); ?> --EXPECT-- Cannot access "self" when no class scope is active Cannot access "parent" when no class scope is active Cannot access "static" when no class scope is active -Cannot access "parent" when current class scope has no parent diff --git a/Zend/tests/pattern_matching/is/binding.phpt b/Zend/tests/pattern_matching/is/binding.phpt index 4ce5dc6e325ff..a6e17ff1fe4a5 100644 --- a/Zend/tests/pattern_matching/is/binding.phpt +++ b/Zend/tests/pattern_matching/is/binding.phpt @@ -42,10 +42,10 @@ var_dump($a); var_dump(new NotBox(43) is Box { value: $a }); var_dump($a); -var_dump(43 is $a @ int); +var_dump(43 is $a & int); var_dump($a); -var_dump([] is $a @ string); +var_dump([] is $a & string); var_dump($a); var_dump(new Many() is Many { $a, $b, $c, $d }); diff --git a/Zend/tests/pattern_matching/is/object.phpt b/Zend/tests/pattern_matching/is/object.phpt index 6f05a7211354b..b0f634b33772a 100644 --- a/Zend/tests/pattern_matching/is/object.phpt +++ b/Zend/tests/pattern_matching/is/object.phpt @@ -34,21 +34,21 @@ $foo = new Foo(42); $bar = new Bar(43); $qux = new Qux(); -var_dump($foo is Foo {}); -var_dump($foo is Bar {}); -var_dump($foo is Baz {}); -var_dump($foo is Qux {}); -var_dump($foo is Quux {}); -var_dump($bar is Foo {}); -var_dump($bar is Bar {}); -var_dump($bar is Baz {}); -var_dump($bar is Qux {}); -var_dump($bar is Quux {}); -var_dump(null is Foo {}); -var_dump(null is Bar {}); -var_dump(null is Baz {}); -var_dump(null is Qux {}); -var_dump(null is Quux {}); +var_dump($foo is Foo); +var_dump($foo is Bar); +var_dump($foo is Baz); +var_dump($foo is Qux); +var_dump($foo is Quux); +var_dump($bar is Foo); +var_dump($bar is Bar); +var_dump($bar is Baz); +var_dump($bar is Qux); +var_dump($bar is Quux); +var_dump(null is Foo); +var_dump(null is Bar); +var_dump(null is Baz); +var_dump(null is Qux); +var_dump(null is Quux); var_dump($foo is Foo { a: 42 }); var_dump($foo is Foo { a: 42|43 }); diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index d6cb748f3fcbe..ed212ac65afe0 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -115,6 +115,7 @@ enum _zend_ast_kind { ZEND_AST_PROPERTY_HOOK_SHORT_BODY, ZEND_AST_TYPE_PATTERN, ZEND_AST_ARRAY_PATTERN, + ZEND_AST_BINDING_PATTERN, /* 2 child nodes */ ZEND_AST_DIM = 2 << ZEND_AST_NUM_CHILDREN_SHIFT, @@ -164,7 +165,6 @@ enum _zend_ast_kind { ZEND_AST_OBJECT_PATTERN_ELEMENT, ZEND_AST_RANGE_PATTERN, ZEND_AST_ARRAY_PATTERN_ELEMENT, - ZEND_AST_BINDING_PATTERN, ZEND_AST_CLASS_CONST_PATTERN, /* 3 child nodes */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f3e5a0cdf5adf..dfc2b972497ab 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6624,43 +6624,6 @@ static void zend_compile_match(znode *result, zend_ast *ast) efree(jmp_end_opnums); } -static void zend_compile_pattern_class_name(zend_ast *ast) -{ - zend_ast *class_name_ast = ast->child[0]; - ZEND_ASSERT(class_name_ast->kind == ZEND_AST_ZVAL); - - zend_string *class_name = zend_ast_get_str(class_name_ast); - uint32_t fetch_type = zend_get_class_fetch_type(class_name); - - switch (fetch_type) { - case ZEND_FETCH_CLASS_SELF: - case ZEND_FETCH_CLASS_PARENT: - case ZEND_FETCH_CLASS_STATIC: - /* For the const-eval representation store the fetch type instead of the name. */ - zend_string_release(class_name); - ast->child[0] = NULL; - ast->attr = fetch_type; - return; - case ZEND_FETCH_CLASS_DEFAULT: { - zend_string *tmp = zend_resolve_class_name_ast(class_name_ast); - zend_string_release_ex(class_name, 0); - if (tmp != class_name) { - zval *zv = zend_ast_get_zval(class_name_ast); - ZVAL_STR(zv, tmp); - class_name_ast->attr = ZEND_NAME_FQ; - } - break; - } - EMPTY_SWITCH_DEFAULT_CASE() - } -} - -static void zend_compile_object_pattern(zend_ast **ast_ptr) -{ - zend_ast *ast = *ast_ptr; - zend_compile_pattern_class_name(ast); -} - static zend_type zend_compile_single_typename(zend_ast *ast); static void zend_compile_type_pattern(zend_ast **ast_ptr) @@ -6682,6 +6645,7 @@ static void zend_compile_type_pattern(zend_ast **ast_ptr) type_pattern_ast->child[0] = NULL; if (ZEND_TYPE_IS_COMPLEX(type)) { + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(type)); zend_string *class_name = ZEND_TYPE_NAME(type); type_pattern_ast->child[0] = zend_ast_create_zval_from_str(class_name); } @@ -6774,9 +6738,6 @@ static void zend_compile_pattern(zend_ast **ast_ptr, void *context) bool prev_inside_or_pattern = pattern_context->inside_or_pattern; switch (ast->kind) { - case ZEND_AST_OBJECT_PATTERN: - zend_compile_object_pattern(ast_ptr); - break; case ZEND_AST_TYPE_PATTERN: zend_compile_type_pattern(ast_ptr); break; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index ed876a65ee766..10642901b1b33 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -964,9 +964,9 @@ attributed_class_statement: property_modifiers optional_type_without_static property_list ';' { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3, NULL); $$->attr = $1; } - | property_modifiers optional_type_without_static hooked_property + /*| property_modifiers optional_type_without_static hooked_property { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, zend_ast_create_list(1, ZEND_AST_PROP_DECL, $3), NULL); - $$->attr = $1; } + $$->attr = $1; }*/ | class_const_modifiers T_CONST class_const_list ';' { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL, NULL); $$->attr = $1; } @@ -1125,7 +1125,7 @@ property_hook_list: optional_property_hook_list: %empty { $$ = NULL; } - | '{' property_hook_list '}' { $$ = $2; } + /*| '{' property_hook_list '}' { $$ = $2; }*/ ; property_hook_modifiers: @@ -1379,8 +1379,8 @@ compound_pattern: ; type_pattern: - type_without_static { $$ = zend_ast_create(ZEND_AST_TYPE_PATTERN, $1); } - | '?' type_without_static { $$ = zend_ast_create(ZEND_AST_TYPE_PATTERN, $2); $2->attr |= ZEND_TYPE_NULLABLE; } + type { $$ = zend_ast_create(ZEND_AST_TYPE_PATTERN, $1); } + | '?' type { $$ = zend_ast_create(ZEND_AST_TYPE_PATTERN, $2); $2->attr |= ZEND_TYPE_NULLABLE; } ; scalar_pattern: @@ -1394,7 +1394,7 @@ scalar_pattern: ; object_pattern: - class_name '{' object_pattern_element_list '}' { $$ = zend_ast_create(ZEND_AST_OBJECT_PATTERN, $1, $3); } + atomic_pattern '{' object_pattern_element_list '}' { $$ = zend_ast_create(ZEND_AST_OBJECT_PATTERN, $1, $3); } ; object_pattern_element_list: @@ -1432,8 +1432,7 @@ range_pattern: ; binding_pattern: - T_VARIABLE { $$ = zend_ast_create(ZEND_AST_BINDING_PATTERN, $1, NULL); } - | T_VARIABLE '@' pattern { $$ = zend_ast_create(ZEND_AST_BINDING_PATTERN, $1, $3); } + T_VARIABLE { $$ = zend_ast_create(ZEND_AST_BINDING_PATTERN, $1); } ; array_pattern: diff --git a/Zend/zend_pattern_matching.c b/Zend/zend_pattern_matching.c index 5ae980ba5b959..a9787b26d0776 100644 --- a/Zend/zend_pattern_matching.c +++ b/Zend/zend_pattern_matching.c @@ -29,26 +29,45 @@ typedef enum { } pm_result; pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern); +static zend_class_entry *get_class_from_fetch_type(uint32_t fetch_type); static pm_result match_type(zval *zv, zend_ast *type_ast) { zend_ast *class_name_ast = type_ast->child[0]; + uint32_t fetch_type; + if (class_name_ast) { if (Z_TYPE_P(zv) != IS_OBJECT) { return PM_MISMATCH; } - zend_object *obj = Z_OBJ_P(zv); zend_string *class_name = zend_ast_get_str(class_name_ast); - if (!zend_string_equals_ci(obj->ce->name, class_name)) { - zend_class_entry *expected_class = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (!expected_class || !instanceof_function(Z_OBJ_P(zv)->ce, expected_class)) { - return PM_MISMATCH; + fetch_type = zend_get_class_fetch_type(class_name); + + zend_class_entry *expected_class = NULL; + if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { + zend_object *obj = Z_OBJ_P(zv); + if (zend_string_equals_ci(obj->ce->name, class_name)) { + return PM_MATCH; } + expected_class = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); + } else { +non_default_fetch_type: + expected_class = get_class_from_fetch_type(fetch_type); + if (!expected_class) { + return PM_ERROR; + } + } + if (!expected_class || !instanceof_function(Z_OBJ_P(zv)->ce, expected_class)) { + return PM_MISMATCH; } } else { zend_type type = ZEND_TYPE_INIT_MASK(type_ast->attr); if (!ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(zv))) { + if (ZEND_TYPE_CONTAINS_CODE(type, IS_STATIC)) { + fetch_type = ZEND_FETCH_CLASS_STATIC; + goto non_default_fetch_type; + } return PM_MISMATCH; } } @@ -105,25 +124,9 @@ static pm_result match_object(zval *zv, zend_ast *pattern) } zend_object *obj = Z_OBJ_P(zv); - zend_ast *class_name_ast = pattern->child[0]; - - if (class_name_ast) { - zend_string *class_name = zend_ast_get_str(class_name_ast); - if (!zend_string_equals_ci(obj->ce->name, class_name)) { - zend_class_entry *expected_class = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (!expected_class || !instanceof_function(Z_OBJ_P(zv)->ce, expected_class)) { - return PM_MISMATCH; - } - } - } else { - uint32_t fetch_type = pattern->attr; - zend_class_entry *scope = get_class_from_fetch_type(fetch_type); - if (EG(exception)) { - return PM_ERROR; - } - if (!instanceof_function(Z_OBJ_P(zv)->ce, scope)) { - return PM_MISMATCH; - } + pm_result type_result = match_type(zv, pattern->child[0]); + if (type_result != PM_MATCH) { + return type_result; } zend_ast_list *elements = zend_ast_get_list(pattern->child[1]); @@ -165,11 +168,6 @@ static pm_result match_range(zval *zv, zend_ast *pattern) static pm_result match_binding(zval *zv, zend_ast *pattern) { - zend_ast *sub_pattern = pattern->child[1]; - if (sub_pattern && !zend_pattern_match_ex(zv, sub_pattern)) { - return PM_MISMATCH; - } - zend_pm_context *context = EG(pm_context); zend_pm_bindings *bindings = context->bindings; if (!bindings) { From 016629087913dab941fc38f8abb838c855773c5b Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Jan 2025 17:42:37 +0100 Subject: [PATCH 3/5] Transform Foo {} to Foo & {} This avoids a grammar ambiguity. --- Zend/tests/pattern_matching/is/binding.phpt | 8 +++---- .../pattern_matching/is/delayed_binding.phpt | 8 +++---- Zend/tests/pattern_matching/is/object.phpt | 24 +++++++++---------- .../pattern_matching/is/object_shorthand.phpt | 4 ++-- Zend/zend_ast.h | 2 +- Zend/zend_language_parser.y | 8 +++---- Zend/zend_pattern_matching.c | 7 +----- 7 files changed, 28 insertions(+), 33 deletions(-) diff --git a/Zend/tests/pattern_matching/is/binding.phpt b/Zend/tests/pattern_matching/is/binding.phpt index a6e17ff1fe4a5..8dfbfb807b9ea 100644 --- a/Zend/tests/pattern_matching/is/binding.phpt +++ b/Zend/tests/pattern_matching/is/binding.phpt @@ -36,10 +36,10 @@ var_dump($a); var_dump('Hello world' is $a); var_dump($a); -var_dump(new Box(42) is Box { value: $a }); +var_dump(new Box(42) is Box & { value: $a }); var_dump($a); -var_dump(new NotBox(43) is Box { value: $a }); +var_dump(new NotBox(43) is Box & { value: $a }); var_dump($a); var_dump(43 is $a & int); @@ -48,10 +48,10 @@ var_dump($a); var_dump([] is $a & string); var_dump($a); -var_dump(new Many() is Many { $a, $b, $c, $d }); +var_dump(new Many() is { $a, $b, $c, $d }); var_dump($a, $b, $c, $d, isset($e)); -var_dump(new Many() is Many { $a, $b, $c, $d, $e, $f, $g, $h, $i, $j }); +var_dump(new Many() is { $a, $b, $c, $d, $e, $f, $g, $h, $i, $j }); var_dump($a, $b, $c, $d, $e, $f, $g, $h, $i, $j); ?> diff --git a/Zend/tests/pattern_matching/is/delayed_binding.phpt b/Zend/tests/pattern_matching/is/delayed_binding.phpt index 7e3edb324173d..e82a9ae096904 100644 --- a/Zend/tests/pattern_matching/is/delayed_binding.phpt +++ b/Zend/tests/pattern_matching/is/delayed_binding.phpt @@ -7,19 +7,19 @@ class Pair { public function __construct(public $a, public $b) {} } -var_dump(new Pair(1, 2) is Pair { a: $a, b: $b }); +var_dump(new Pair(1, 2) is { a: $a, b: $b }); var_dump($a, $b); unset($a, $b); -var_dump(new Pair(1, 2) is Pair { a: $a, b: 3 }); +var_dump(new Pair(1, 2) is { a: $a, b: 3 }); var_dump($a, $b); unset($a, $b); -var_dump(new Pair(new \stdClass(), 2) is Pair { a: $a, b: 2 }); +var_dump(new Pair(new \stdClass(), 2) is { a: $a, b: 2 }); var_dump($a, $b); unset($a, $b); -var_dump(new Pair(new \stdClass(), 2) is Pair { a: $a, b: 3 }); +var_dump(new Pair(new \stdClass(), 2) is { a: $a, b: 3 }); var_dump($a, $b); unset($a, $b); diff --git a/Zend/tests/pattern_matching/is/object.phpt b/Zend/tests/pattern_matching/is/object.phpt index b0f634b33772a..a2002ca8f6667 100644 --- a/Zend/tests/pattern_matching/is/object.phpt +++ b/Zend/tests/pattern_matching/is/object.phpt @@ -9,21 +9,21 @@ class Foo { ) {} public static function isSelfFoo($value) { - return $value is self {}; + return $value is self; } public static function isStaticFoo($value) { - return $value is static {}; + return $value is static; } } class Bar extends Foo implements Baz { public static function isSelfBar($value) { - return $value is self {}; + return $value is self; } public static function isParentBar($value) { - return $value is parent {}; + return $value is parent; } } @@ -50,14 +50,14 @@ var_dump(null is Baz); var_dump(null is Qux); var_dump(null is Quux); -var_dump($foo is Foo { a: 42 }); -var_dump($foo is Foo { a: 42|43 }); -var_dump($foo is Foo { a: 'hello world' }); -var_dump($foo is Foo { b: 42 }); -var_dump($bar is Foo { a: 42 }); -var_dump($bar is Foo { a: 42|43 }); -var_dump($bar is Foo { a: 'hello world' }); -var_dump($bar is Foo { b: 42 }); +var_dump($foo is { a: 42 }); +var_dump($foo is { a: 42|43 }); +var_dump($foo is { a: 'hello world' }); +var_dump($foo is { b: 42 }); +var_dump($bar is { a: 42 }); +var_dump($bar is { a: 42|43 }); +var_dump($bar is { a: 'hello world' }); +var_dump($bar is { b: 42 }); var_dump(Foo::isSelfFoo($foo)); var_dump(Foo::isSelfFoo($bar)); diff --git a/Zend/tests/pattern_matching/is/object_shorthand.phpt b/Zend/tests/pattern_matching/is/object_shorthand.phpt index ad269ae855342..61786df10ad4e 100644 --- a/Zend/tests/pattern_matching/is/object_shorthand.phpt +++ b/Zend/tests/pattern_matching/is/object_shorthand.phpt @@ -7,9 +7,9 @@ class Foo { public function __construct(public $a, public $b) {} } -var_dump(new Foo(1, 2) is Foo { $a, b: 2 }); +var_dump(new Foo(1, 2) is { $a, b: 2 }); var_dump($a); -var_dump(new Foo(1, 2) is Foo { a: 3, $b }); +var_dump(new Foo(1, 2) is { a: 3, $b }); var_dump($b); ?> diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index ed212ac65afe0..a76427a9c41b4 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -116,6 +116,7 @@ enum _zend_ast_kind { ZEND_AST_TYPE_PATTERN, ZEND_AST_ARRAY_PATTERN, ZEND_AST_BINDING_PATTERN, + ZEND_AST_OBJECT_PATTERN, /* 2 child nodes */ ZEND_AST_DIM = 2 << ZEND_AST_NUM_CHILDREN_SHIFT, @@ -161,7 +162,6 @@ enum _zend_ast_kind { ZEND_AST_IS, ZEND_AST_OR_PATTERN, ZEND_AST_AND_PATTERN, - ZEND_AST_OBJECT_PATTERN, ZEND_AST_OBJECT_PATTERN_ELEMENT, ZEND_AST_RANGE_PATTERN, ZEND_AST_ARRAY_PATTERN_ELEMENT, diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 10642901b1b33..2d2990182cd26 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -964,9 +964,9 @@ attributed_class_statement: property_modifiers optional_type_without_static property_list ';' { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3, NULL); $$->attr = $1; } - /*| property_modifiers optional_type_without_static hooked_property + | property_modifiers optional_type_without_static hooked_property { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, zend_ast_create_list(1, ZEND_AST_PROP_DECL, $3), NULL); - $$->attr = $1; }*/ + $$->attr = $1; } | class_const_modifiers T_CONST class_const_list ';' { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL, NULL); $$->attr = $1; } @@ -1125,7 +1125,7 @@ property_hook_list: optional_property_hook_list: %empty { $$ = NULL; } - /*| '{' property_hook_list '}' { $$ = $2; }*/ + | '{' property_hook_list '}' { $$ = $2; } ; property_hook_modifiers: @@ -1394,7 +1394,7 @@ scalar_pattern: ; object_pattern: - atomic_pattern '{' object_pattern_element_list '}' { $$ = zend_ast_create(ZEND_AST_OBJECT_PATTERN, $1, $3); } + '{' object_pattern_element_list '}' { $$ = zend_ast_create(ZEND_AST_OBJECT_PATTERN, $2); } ; object_pattern_element_list: diff --git a/Zend/zend_pattern_matching.c b/Zend/zend_pattern_matching.c index a9787b26d0776..f7a726a0fa83c 100644 --- a/Zend/zend_pattern_matching.c +++ b/Zend/zend_pattern_matching.c @@ -124,12 +124,7 @@ static pm_result match_object(zval *zv, zend_ast *pattern) } zend_object *obj = Z_OBJ_P(zv); - pm_result type_result = match_type(zv, pattern->child[0]); - if (type_result != PM_MATCH) { - return type_result; - } - - zend_ast_list *elements = zend_ast_get_list(pattern->child[1]); + zend_ast_list *elements = zend_ast_get_list(pattern->child[0]); for (uint32_t i = 0; i < elements->children; i++) { zend_ast *element = elements->child[i]; zend_ast *property_or_method_call = element->child[0]; From aa1974230d1dc07e304aa6ed9a259d4a3c2f7b97 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 1 Feb 2025 18:02:35 +0100 Subject: [PATCH 4/5] Transform pattern bindings to opcodes This solves issues with the optimizer where it would be unaware of the assignments that happen inside the pattern matcher. Instead, we now emit an array of bindings in op2, and extract & assign the values to the given variables through opcodes. --- .../pattern_matching/is/binding_destruct.phpt | 2 +- Zend/tests/pattern_matching/is/bug_001.phpt | 16 +++ Zend/zend_compile.c | 101 +++++++++++--- Zend/zend_execute_API.c | 2 - Zend/zend_globals.h | 2 - Zend/zend_opcode.c | 6 +- Zend/zend_pattern_matching.c | 132 ++++-------------- Zend/zend_pattern_matching.h | 25 +--- Zend/zend_vm_def.h | 23 ++- Zend/zend_vm_execute.h | 51 ++++--- Zend/zend_vm_handlers.h | 2 +- Zend/zend_vm_opcodes.c | 2 +- 12 files changed, 187 insertions(+), 177 deletions(-) create mode 100644 Zend/tests/pattern_matching/is/bug_001.phpt diff --git a/Zend/tests/pattern_matching/is/binding_destruct.phpt b/Zend/tests/pattern_matching/is/binding_destruct.phpt index 7ceea9972c619..d99c8d73549b5 100644 --- a/Zend/tests/pattern_matching/is/binding_destruct.phpt +++ b/Zend/tests/pattern_matching/is/binding_destruct.phpt @@ -25,4 +25,4 @@ var_dump($bar); --EXPECT-- Here int(42) -int(42) +string(3) "bar" diff --git a/Zend/tests/pattern_matching/is/bug_001.phpt b/Zend/tests/pattern_matching/is/bug_001.phpt new file mode 100644 index 0000000000000..1a4f2d417d2c5 --- /dev/null +++ b/Zend/tests/pattern_matching/is/bug_001.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug 001 +--FILE-- + +--EXPECT-- +int(43) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index dfc2b972497ab..2094614870e67 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6418,6 +6418,12 @@ static bool can_match_use_jumptable(zend_ast_list *arms) { static void zend_compile_pattern(zend_ast **ast_ptr, void *context); +typedef struct { + bool inside_or_pattern; + uint32_t bindings_var; + uint32_t binding_offset; +} zend_compile_pattern_context; + static void zend_compile_match(znode *result, zend_ast *ast) { zend_ast *expr_ast = ast->child[0]; @@ -6491,7 +6497,23 @@ static void zend_compile_match(znode *result, zend_ast *ast) } else { zend_ast **pattern_ast_ptr = &cond_ast->child[1]; - zend_compile_pattern(pattern_ast_ptr, NULL); + znode bindings_node; + bindings_node.op_type = IS_TMP_VAR; + bindings_node.u.op.var = get_temporary_variable(); + + uint32_t is_opnum = get_next_op_number(); + zend_op *is_opline = zend_emit_op_tmp(NULL, ZEND_IS, &expr_node, &bindings_node); + SET_NODE(is_opline->result, &case_node); + if (is_opline->op1_type == IS_CONST) { + Z_TRY_ADDREF_P(CT_CONSTANT(is_opline->op1)); + } + + uint32_t op_data_opnum = get_next_op_number(); + zend_emit_op_data(NULL); + + zend_compile_pattern_context pattern_context = { .bindings_var = bindings_node.u.op.var }; + zend_compile_pattern(pattern_ast_ptr, &pattern_context); + zval pattern_zv; ZVAL_AST(&pattern_zv, zend_ast_copy(*pattern_ast_ptr)); zend_ast_destroy(*pattern_ast_ptr); @@ -6500,11 +6522,20 @@ static void zend_compile_match(znode *result, zend_ast *ast) znode pattern_node; pattern_node.op_type = IS_CONST; ZVAL_COPY(&pattern_node.u.constant, &pattern_zv); + zend_op *op_data_op = &CG(active_op_array)->opcodes[op_data_opnum]; + SET_NODE(op_data_op->op1, &pattern_node); + op_data_op->extended_value = pattern_context.binding_offset; - zend_op *opline = zend_emit_op_tmp(NULL, ZEND_IS, &expr_node, &pattern_node); - SET_NODE(opline->result, &case_node); - if (opline->op1_type == IS_CONST) { - Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1)); + is_opline = &CG(active_op_array)->opcodes[is_opnum]; + is_opline->extended_value = get_next_op_number(); + + if (pattern_context.binding_offset) { + zend_emit_op(NULL, ZEND_FREE, &bindings_node, NULL); + } + + if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) { + // FIXME: Verify live ranges recognizes that OP1 needs to be freed if an exception occurs + zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); } } @@ -6658,16 +6689,37 @@ static void zend_compile_class_const_pattern(zend_ast **ast_ptr) // zend_compile_pattern_class_name(ast); } -static void zend_compile_binding_pattern(zend_ast **ast_ptr) +static void zend_compile_binding_pattern(zend_ast **ast_ptr, zend_compile_pattern_context *context) { zend_ast *binding_pattern_ast = *ast_ptr; zend_ast *var_name_ast = binding_pattern_ast->child[0]; zend_string *var_name = zend_ast_get_str(var_name_ast); uint32_t var = lookup_cv(var_name); + uint32_t binding_offset = context->binding_offset++; + zend_ast_destroy(var_name_ast); binding_pattern_ast->child[0] = NULL; - binding_pattern_ast->attr = var; + binding_pattern_ast->attr = binding_offset; + + znode bindings_node; + bindings_node.op_type = IS_TMP_VAR; + bindings_node.u.op.var = context->bindings_var; + + znode offset_node; + offset_node.op_type = IS_CONST; + ZVAL_LONG(&offset_node.u.constant, binding_offset); + + znode copy_tmp_node; + zend_emit_op_tmp(©_tmp_node, ZEND_COPY_TMP, &bindings_node, NULL); + + znode dim_result; + zend_emit_op_tmp(&dim_result, ZEND_FETCH_DIM_R, ©_tmp_node, &offset_node); + + znode var_node; + var_node.op_type = IS_CV; + var_node.u.op.var = var; + zend_emit_op_tmp(NULL, ZEND_ASSIGN, &var_node, &dim_result); } static void zend_compile_array_pattern(zend_ast **ast_ptr) @@ -6719,10 +6771,6 @@ static void zend_compile_and_pattern(zend_ast **ast_ptr) verify_parenthesized_compound_pattern(ast_ptr, ZEND_AST_OR_PATTERN); } -struct zend_compile_pattern_context { - bool inside_or_pattern; -}; - static void zend_compile_pattern(zend_ast **ast_ptr, void *context) { zend_ast *ast = *ast_ptr; @@ -6730,8 +6778,8 @@ static void zend_compile_pattern(zend_ast **ast_ptr, void *context) return; } - struct zend_compile_pattern_context *pattern_context = context; - struct zend_compile_pattern_context tmp_context = {0}; + zend_compile_pattern_context *pattern_context = context; + zend_compile_pattern_context tmp_context = {0}; if (!pattern_context) { pattern_context = &tmp_context; } @@ -6745,7 +6793,7 @@ static void zend_compile_pattern(zend_ast **ast_ptr, void *context) if (pattern_context->inside_or_pattern) { zend_throw_exception(zend_ce_compile_error, "Must not bind to variables inside | pattern", 0); } - zend_compile_binding_pattern(ast_ptr); + zend_compile_binding_pattern(ast_ptr, context); break; case ZEND_AST_ARRAY_PATTERN: zend_compile_array_pattern(ast_ptr); @@ -6774,7 +6822,19 @@ static void zend_compile_is(znode *result, zend_ast *ast) znode expr_node; zend_compile_expr(&expr_node, expr_ast); - zend_compile_pattern(pattern_ast_ptr, NULL); + znode bindings_node; + bindings_node.op_type = IS_TMP_VAR; + bindings_node.u.op.var = get_temporary_variable(); + + uint32_t is_opnum = get_next_op_number(); + zend_emit_op_tmp(result, ZEND_IS, &expr_node, &bindings_node); + + uint32_t op_data_opnum = get_next_op_number(); + zend_emit_op_data(NULL); + + zend_compile_pattern_context pattern_context = { .bindings_var = bindings_node.u.op.var }; + zend_compile_pattern(pattern_ast_ptr, &pattern_context); + zval pattern_zv; ZVAL_AST(&pattern_zv, zend_ast_copy(*pattern_ast_ptr)); zend_ast_destroy(*pattern_ast_ptr); @@ -6783,8 +6843,17 @@ static void zend_compile_is(znode *result, zend_ast *ast) znode pattern_node; pattern_node.op_type = IS_CONST; ZVAL_COPY(&pattern_node.u.constant, &pattern_zv); + zend_op *op_data_op = &CG(active_op_array)->opcodes[op_data_opnum]; + SET_NODE(op_data_op->op1, &pattern_node); + op_data_op->extended_value = pattern_context.binding_offset; + + zend_op *is_opline = &CG(active_op_array)->opcodes[is_opnum]; + is_opline->extended_value = get_next_op_number(); + + if (pattern_context.binding_offset) { + zend_emit_op(NULL, ZEND_FREE, &bindings_node, NULL); + } - zend_emit_op_tmp(result, ZEND_IS, &expr_node, &pattern_node); if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) { // FIXME: Verify live ranges recognizes that OP1 needs to be freed if an exception occurs zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 0a9810baf2c90..74492df3b79f8 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -206,8 +206,6 @@ void init_executor(void) /* {{{ */ zend_fiber_init(); zend_weakrefs_init(); - zend_pm_contexts_free(); - EG(active) = 1; } /* }}} */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 9d4163517a72e..d414ff13222eb 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -314,8 +314,6 @@ struct _zend_executor_globals { #endif zend_strtod_state strtod_state; - zend_pm_context *pm_context; - zend_pm_context pm_context_spare; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 28d9c6712fb5a..0ca89f7272a50 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -979,7 +979,8 @@ static void zend_calc_live_ranges( if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { uint32_t var_num = EX_VAR_TO_NUM(opline->op2.var) - var_offset; if (UNEXPECTED(opline->opcode == ZEND_FE_FETCH_R - || opline->opcode == ZEND_FE_FETCH_RW)) { + || opline->opcode == ZEND_FE_FETCH_RW + || opline->opcode == ZEND_IS)) { /* OP2 of FE_FETCH is actually a def, not a use. */ if (last_use[var_num] != (uint32_t) -1) { if (opnum + 1 != last_use[var_num]) { @@ -1184,6 +1185,9 @@ ZEND_API void pass_two(zend_op_array *op_array) opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); break; } + case ZEND_IS: + opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); + break; } if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1); diff --git a/Zend/zend_pattern_matching.c b/Zend/zend_pattern_matching.c index f7a726a0fa83c..40b2c3ce7a87b 100644 --- a/Zend/zend_pattern_matching.c +++ b/Zend/zend_pattern_matching.c @@ -28,7 +28,11 @@ typedef enum { PM_MATCH = 1, } pm_result; -pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern); +typedef struct { + zend_array *bindings; +} pm_context; + +pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern, pm_context *context); static zend_class_entry *get_class_from_fetch_type(uint32_t fetch_type); static pm_result match_type(zval *zv, zend_ast *type_ast) @@ -117,7 +121,7 @@ static zend_class_entry *get_class_from_fetch_type(uint32_t fetch_type) return NULL; } -static pm_result match_object(zval *zv, zend_ast *pattern) +static pm_result match_object(zval *zv, zend_ast *pattern, pm_context *context) { if (Z_TYPE_P(zv) != IS_OBJECT) { return PM_MISMATCH; @@ -132,7 +136,7 @@ static pm_result match_object(zval *zv, zend_ast *pattern) zend_string *property_name = zend_ast_get_str(property_or_method_call); zval property_result_rv; zval *property_result = obj->handlers->read_property(obj, property_name, BP_VAR_R, NULL, &property_result_rv); - pm_result element_matched = zend_pattern_match_ex(property_result, element_pattern); + pm_result element_matched = zend_pattern_match_ex(property_result, element_pattern, context); if (property_result == &property_result_rv) { zval_ptr_dtor(property_result); } @@ -161,31 +165,15 @@ static pm_result match_range(zval *zv, zend_ast *pattern) return PM_MATCH; } -static pm_result match_binding(zval *zv, zend_ast *pattern) +static pm_result match_binding(zval *zv, zend_ast *pattern, pm_context *context) { - zend_pm_context *context = EG(pm_context); - zend_pm_bindings *bindings = context->bindings; - if (!bindings) { - bindings = &context->bindings_spare; - context->bindings = bindings; - context->last_bindings = bindings; - } else if (bindings->num_used == ZEND_PM_BINDINGS_SLOTS) { - zend_pm_bindings *new_bindings = emalloc(sizeof(zend_pm_bindings)); - new_bindings->num_used = 0; - new_bindings->next = NULL; - context->last_bindings->next = new_bindings; - context->last_bindings = new_bindings; - bindings = new_bindings; - } - - zend_pm_binding *binding = &bindings->list[bindings->num_used++]; - binding->var = (uint32_t) pattern->attr; - ZVAL_COPY(&binding->value, zv); - + ZVAL_DEREF(zv); + Z_TRY_ADDREF_P(zv); + zend_hash_index_add(context->bindings, (zend_ulong) pattern->attr, zv); return PM_MATCH; } -static pm_result match_array(zval *zv, zend_ast *pattern) +static pm_result match_array(zval *zv, zend_ast *pattern, pm_context *context) { if (Z_TYPE_P(zv) != IS_ARRAY) { return PM_MISMATCH; @@ -225,7 +213,7 @@ static pm_result match_array(zval *zv, zend_ast *pattern) element_zv = zend_hash_index_find(ht, index); index++; } - if (!element_zv || Z_TYPE_P(element_zv) == IS_UNDEF || !zend_pattern_match_ex(element_zv, pattern_ast)) { + if (!element_zv || Z_TYPE_P(element_zv) == IS_UNDEF || !zend_pattern_match_ex(element_zv, pattern_ast, context)) { return PM_MISMATCH; } } @@ -246,7 +234,7 @@ pm_result match_class_const(zval *zv, zend_ast *pattern) return zend_is_identical(zv, constant_zv) ? PM_MATCH : PM_MISMATCH; } -pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern) +pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern, pm_context *context) { ZVAL_DEREF(zv); @@ -256,108 +244,38 @@ pm_result zend_pattern_match_ex(zval *zv, zend_ast *pattern) case ZEND_AST_ZVAL: return match_zval(zv, zend_ast_get_zval(pattern)); case ZEND_AST_OBJECT_PATTERN: - return match_object(zv, pattern); + return match_object(zv, pattern, context); case ZEND_AST_WILDCARD_PATTERN: return PM_MATCH; case ZEND_AST_OR_PATTERN: { - pm_result lhs = zend_pattern_match_ex(zv, pattern->child[0]); + pm_result lhs = zend_pattern_match_ex(zv, pattern->child[0], context); if (lhs != PM_MISMATCH) { return lhs; } - return zend_pattern_match_ex(zv, pattern->child[1]); + return zend_pattern_match_ex(zv, pattern->child[1], context); } case ZEND_AST_AND_PATTERN: { - pm_result lhs = zend_pattern_match_ex(zv, pattern->child[0]); + pm_result lhs = zend_pattern_match_ex(zv, pattern->child[0], context); if (lhs != PM_MATCH) { return lhs; } - return zend_pattern_match_ex(zv, pattern->child[1]); + return zend_pattern_match_ex(zv, pattern->child[1], context); } case ZEND_AST_RANGE_PATTERN: return match_range(zv, pattern); case ZEND_AST_BINDING_PATTERN: - return match_binding(zv, pattern); + return match_binding(zv, pattern, context); case ZEND_AST_ARRAY_PATTERN: - return match_array(zv, pattern); + return match_array(zv, pattern, context); case ZEND_AST_CLASS_CONST_PATTERN: return match_class_const(zv, pattern); EMPTY_SWITCH_DEFAULT_CASE(); } } -static void create_context(void) -{ - if (!EG(pm_context)) { - EG(pm_context) = &EG(pm_context_spare); - } else { - zend_pm_context *prev = EG(pm_context); - EG(pm_context) = emalloc(sizeof(zend_pm_context)); - EG(pm_context)->prev = prev; - } -} - -static void pm_context_free(bool free_values) -{ - zend_pm_context *context = EG(pm_context); - zend_pm_bindings *bindings = context->bindings; - - EG(pm_context) = context->prev; - - while (bindings) { - if (free_values) { - for (uint8_t i = 0; i < bindings->num_used; i++) { - zval_ptr_dtor(&bindings->list[i].value); - } - } - zend_pm_bindings *next = bindings->next; - if (bindings != &context->bindings_spare) { - efree(bindings); - } - bindings = next; - } - - context->bindings = NULL; - memset(&context->bindings_spare, 0, sizeof(context->bindings_spare)); - - if (context != &EG(pm_context_spare)) { - efree(context); - } else { - memset(context, 0, sizeof(zend_pm_context)); - } -} - -static void bind_variables(void) +bool zend_pattern_match(zval *zv, zend_ast *pattern, zend_array *bindings) { - zend_pm_context *context = EG(pm_context); - zend_pm_bindings *bindings = context->bindings; - zend_execute_data *execute_data = EG(current_execute_data); - while (bindings) { - for (uint32_t i = 0; i < bindings->num_used; i++) { - zend_pm_binding *binding = &bindings->list[i]; - zend_assign_to_variable(EX_VAR(binding->var), &binding->value, IS_CV, EX_USES_STRICT_TYPES()); - } - bindings = bindings->next; - } -} - -void zend_pm_contexts_free(void) -{ - while (EG(pm_context)) { - pm_context_free(false); - } -} - -bool zend_pattern_match(zval *zv, zend_ast *pattern) -{ - // FIXME: Only create context when necessary - create_context(); - pm_result result = zend_pattern_match_ex(zv, pattern); - if (result == PM_MATCH) { - bind_variables(); - pm_context_free(true); - return true; - } else { - pm_context_free(true); - return false; - } + pm_context context = { .bindings = bindings }; + pm_result result = zend_pattern_match_ex(zv, pattern, &context); + return result == PM_MATCH; } diff --git a/Zend/zend_pattern_matching.h b/Zend/zend_pattern_matching.h index 673c947d1f416..4bb3616547226 100644 --- a/Zend/zend_pattern_matching.h +++ b/Zend/zend_pattern_matching.h @@ -19,29 +19,6 @@ #include "zend.h" -#define ZEND_PM_BINDINGS_SLOTS 8 - -typedef struct { - uint32_t var; - zval value; -} zend_pm_binding; - -typedef struct _zend_pm_bindings zend_pm_bindings; -struct _zend_pm_bindings { - zend_pm_binding list[ZEND_PM_BINDINGS_SLOTS]; - zend_pm_bindings *next; - uint8_t num_used; -}; - -typedef struct _zend_pm_context zend_pm_context; -typedef struct _zend_pm_context { - zend_pm_bindings *bindings; - zend_pm_bindings *last_bindings; - zend_pm_bindings bindings_spare; - zend_pm_context *prev; -} zend_pm_context; - -bool zend_pattern_match(zval *zv, zend_ast *pattern); -void zend_pm_contexts_free(void); +bool zend_pattern_match(zval *zv, zend_ast *pattern, zend_array *bindings); #endif diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index be00302c6464d..80df92a6c64a6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9299,15 +9299,30 @@ ZEND_VM_C_LABEL(default_branch): } } -ZEND_VM_HANDLER(210, ZEND_IS, ANY, CONST) +ZEND_VM_HANDLER(210, ZEND_IS, ANY, TMPVAR, JMP_ADDR) { + // , SPEC(OP_DATA=CONST) USE_OPLINE SAVE_OPLINE(); zval *expr = GET_OP1_ZVAL_PTR(BP_VAR_R); - zval *pattern = GET_OP2_ZVAL_PTR(BP_VAR_R); - bool result = zend_pattern_match(expr, Z_ASTVAL_P(pattern)); + zend_array *bindings = NULL; + if ((opline+1)->extended_value) { + bindings = zend_new_array((opline+1)->extended_value); + zend_hash_real_init_packed(bindings); + ZVAL_ARR(EX_VAR(opline->op2.var), bindings); + } + zval *pattern = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); + bool result = zend_pattern_match(expr, Z_ASTVAL_P(pattern), bindings); ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + if (result) { + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } else { + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } } ZEND_VM_COLD_CONST_HANDLER(197, ZEND_MATCH_ERROR, CONST|TMPVARCV, UNUSED) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index f4681963b043a..e5708f7bd5be6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4117,17 +4117,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - SAVE_OPLINE(); - zval *expr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); - zval *pattern = RT_CONSTANT(opline, opline->op2); - bool result = zend_pattern_match(expr, Z_ASTVAL_P(pattern)); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4181,6 +4170,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + // , SPEC(OP_DATA=CONST) + USE_OPLINE + SAVE_OPLINE(); + zval *expr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + zend_array *bindings = NULL; + if ((opline+1)->extended_value) { + bindings = zend_new_array((opline+1)->extended_value); + zend_hash_real_init_packed(bindings); + ZVAL_ARR(EX_VAR(opline->op2.var), bindings); + } + zval *pattern = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + bool result = zend_pattern_match(expr, Z_ASTVAL_P(pattern), bindings); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + if (result) { + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } else { + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -57654,7 +57669,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_LABEL, (void*)&&ZEND_JMP_FRAMELESS_SPEC_CONST_LABEL, (void*)&&ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_LABEL, - (void*)&&ZEND_IS_SPEC_CONST_LABEL, + (void*)&&ZEND_IS_SPEC_TMPVAR_LABEL, (void*)&&ZEND_INIT_FCALL_OFFSET_SPEC_CONST_LABEL, (void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -59057,16 +59072,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_RECV_INIT_SPEC_CONST) HYBRID_BREAK(); - HYBRID_CASE(ZEND_IS_SPEC_CONST): - VM_TRACE(ZEND_IS_SPEC_CONST) - ZEND_IS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_IS_SPEC_CONST) - HYBRID_BREAK(); HYBRID_CASE(ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR): VM_TRACE(ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR) ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR) HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_SPEC_TMPVAR): + VM_TRACE(ZEND_IS_SPEC_TMPVAR) + ZEND_IS_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_IS_SPEC_TMPVAR) + HYBRID_BREAK(); HYBRID_CASE(ZEND_RECV_SPEC_UNUSED): VM_TRACE(ZEND_RECV_SPEC_UNUSED) ZEND_RECV_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -66847,7 +66862,7 @@ void zend_vm_init(void) ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_HANDLER, ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER, - ZEND_IS_SPEC_CONST_HANDLER, + ZEND_IS_SPEC_TMPVAR_HANDLER, ZEND_INIT_FCALL_OFFSET_SPEC_CONST_HANDLER, ZEND_RECV_NOTYPE_SPEC_HANDLER, ZEND_NULL_HANDLER, diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 6472580efa999..f658ebbe4ac7b 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1372,7 +1372,7 @@ _(2574, ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER) \ _(2575, ZEND_JMP_FRAMELESS_SPEC_CONST) \ _(2576, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED) \ - _(2577, ZEND_IS_SPEC_CONST) \ + _(2577, ZEND_IS_SPEC_TMPVAR) \ _(2578, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \ _(2579, ZEND_RECV_NOTYPE_SPEC) \ _(2581, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 66ea5c4e7afa1..9347155628dcb 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -447,7 +447,7 @@ static uint32_t zend_vm_opcodes_flags[211] = { 0x00000000, 0x01042003, 0x01001103, - 0x00000300, + 0x03000500, }; ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) { From 4e573ee911e9aba0521cdb65a557786a583efed9 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 2 Feb 2025 21:44:03 +0100 Subject: [PATCH 5/5] Avoid code duplication, fix rc bugs --- Zend/tests/pattern_matching/is/rcd_expr.phpt | 19 ++++++ Zend/zend_compile.c | 66 ++++++-------------- 2 files changed, 37 insertions(+), 48 deletions(-) create mode 100644 Zend/tests/pattern_matching/is/rcd_expr.phpt diff --git a/Zend/tests/pattern_matching/is/rcd_expr.phpt b/Zend/tests/pattern_matching/is/rcd_expr.phpt new file mode 100644 index 0000000000000..f76c80262f0ab --- /dev/null +++ b/Zend/tests/pattern_matching/is/rcd_expr.phpt @@ -0,0 +1,19 @@ +--TEST-- +Refcoutned expression +--FILE-- + throw new Exception('Unreachable'), + is Foo => 'foo', +}); + +?> +--EXPECT-- +bool(true) +bool(false) +string(3) "foo" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2094614870e67..07bb7c0944b1a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6417,6 +6417,7 @@ static bool can_match_use_jumptable(zend_ast_list *arms) { } static void zend_compile_pattern(zend_ast **ast_ptr, void *context); +static uint32_t zend_emit_is(znode *result, znode *expr_node, zend_ast **pattern_ast_ptr); typedef struct { bool inside_or_pattern; @@ -6496,47 +6497,9 @@ static void zend_compile_match(znode *result, zend_ast *ast) } } else { zend_ast **pattern_ast_ptr = &cond_ast->child[1]; - - znode bindings_node; - bindings_node.op_type = IS_TMP_VAR; - bindings_node.u.op.var = get_temporary_variable(); - - uint32_t is_opnum = get_next_op_number(); - zend_op *is_opline = zend_emit_op_tmp(NULL, ZEND_IS, &expr_node, &bindings_node); + uint32_t is_opnum = zend_emit_is(NULL, &expr_node, pattern_ast_ptr); + zend_op *is_opline = &CG(active_op_array)->opcodes[is_opnum]; SET_NODE(is_opline->result, &case_node); - if (is_opline->op1_type == IS_CONST) { - Z_TRY_ADDREF_P(CT_CONSTANT(is_opline->op1)); - } - - uint32_t op_data_opnum = get_next_op_number(); - zend_emit_op_data(NULL); - - zend_compile_pattern_context pattern_context = { .bindings_var = bindings_node.u.op.var }; - zend_compile_pattern(pattern_ast_ptr, &pattern_context); - - zval pattern_zv; - ZVAL_AST(&pattern_zv, zend_ast_copy(*pattern_ast_ptr)); - zend_ast_destroy(*pattern_ast_ptr); - *pattern_ast_ptr = zend_ast_create_zval(&pattern_zv); - - znode pattern_node; - pattern_node.op_type = IS_CONST; - ZVAL_COPY(&pattern_node.u.constant, &pattern_zv); - zend_op *op_data_op = &CG(active_op_array)->opcodes[op_data_opnum]; - SET_NODE(op_data_op->op1, &pattern_node); - op_data_op->extended_value = pattern_context.binding_offset; - - is_opline = &CG(active_op_array)->opcodes[is_opnum]; - is_opline->extended_value = get_next_op_number(); - - if (pattern_context.binding_offset) { - zend_emit_op(NULL, ZEND_FREE, &bindings_node, NULL); - } - - if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) { - // FIXME: Verify live ranges recognizes that OP1 needs to be freed if an exception occurs - zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); - } } jmpnz_opnums[cond_count] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0); @@ -6814,20 +6777,14 @@ static void zend_compile_pattern(zend_ast **ast_ptr, void *context) pattern_context->inside_or_pattern = prev_inside_or_pattern; } -static void zend_compile_is(znode *result, zend_ast *ast) +static uint32_t zend_emit_is(znode *result, znode *expr_node, zend_ast **pattern_ast_ptr) { - zend_ast *expr_ast = ast->child[0]; - zend_ast **pattern_ast_ptr = &ast->child[1]; - - znode expr_node; - zend_compile_expr(&expr_node, expr_ast); - znode bindings_node; bindings_node.op_type = IS_TMP_VAR; bindings_node.u.op.var = get_temporary_variable(); uint32_t is_opnum = get_next_op_number(); - zend_emit_op_tmp(result, ZEND_IS, &expr_node, &bindings_node); + zend_emit_op_tmp(result, ZEND_IS, expr_node, &bindings_node); uint32_t op_data_opnum = get_next_op_number(); zend_emit_op_data(NULL); @@ -6854,6 +6811,19 @@ static void zend_compile_is(znode *result, zend_ast *ast) zend_emit_op(NULL, ZEND_FREE, &bindings_node, NULL); } + return is_opnum; +} + +static void zend_compile_is(znode *result, zend_ast *ast) +{ + zend_ast *expr_ast = ast->child[0]; + zend_ast **pattern_ast_ptr = &ast->child[1]; + + znode expr_node; + zend_compile_expr(&expr_node, expr_ast); + + zend_emit_is(result, &expr_node, pattern_ast_ptr); + if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) { // FIXME: Verify live ranges recognizes that OP1 needs to be freed if an exception occurs zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);