Skip to content

Commit 4e573ee

Browse files
committed
Avoid code duplication, fix rc bugs
1 parent aa19742 commit 4e573ee

File tree

2 files changed

+37
-48
lines changed

2 files changed

+37
-48
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Refcoutned expression
3+
--FILE--
4+
<?php
5+
6+
class Foo {}
7+
8+
var_dump(new Foo() is Foo);
9+
var_dump(new Foo() is Bar);
10+
var_dump(match (new Foo()) {
11+
is Bar => throw new Exception('Unreachable'),
12+
is Foo => 'foo',
13+
});
14+
15+
?>
16+
--EXPECT--
17+
bool(true)
18+
bool(false)
19+
string(3) "foo"

Zend/zend_compile.c

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6417,6 +6417,7 @@ static bool can_match_use_jumptable(zend_ast_list *arms) {
64176417
}
64186418

64196419
static void zend_compile_pattern(zend_ast **ast_ptr, void *context);
6420+
static uint32_t zend_emit_is(znode *result, znode *expr_node, zend_ast **pattern_ast_ptr);
64206421

64216422
typedef struct {
64226423
bool inside_or_pattern;
@@ -6496,47 +6497,9 @@ static void zend_compile_match(znode *result, zend_ast *ast)
64966497
}
64976498
} else {
64986499
zend_ast **pattern_ast_ptr = &cond_ast->child[1];
6499-
6500-
znode bindings_node;
6501-
bindings_node.op_type = IS_TMP_VAR;
6502-
bindings_node.u.op.var = get_temporary_variable();
6503-
6504-
uint32_t is_opnum = get_next_op_number();
6505-
zend_op *is_opline = zend_emit_op_tmp(NULL, ZEND_IS, &expr_node, &bindings_node);
6500+
uint32_t is_opnum = zend_emit_is(NULL, &expr_node, pattern_ast_ptr);
6501+
zend_op *is_opline = &CG(active_op_array)->opcodes[is_opnum];
65066502
SET_NODE(is_opline->result, &case_node);
6507-
if (is_opline->op1_type == IS_CONST) {
6508-
Z_TRY_ADDREF_P(CT_CONSTANT(is_opline->op1));
6509-
}
6510-
6511-
uint32_t op_data_opnum = get_next_op_number();
6512-
zend_emit_op_data(NULL);
6513-
6514-
zend_compile_pattern_context pattern_context = { .bindings_var = bindings_node.u.op.var };
6515-
zend_compile_pattern(pattern_ast_ptr, &pattern_context);
6516-
6517-
zval pattern_zv;
6518-
ZVAL_AST(&pattern_zv, zend_ast_copy(*pattern_ast_ptr));
6519-
zend_ast_destroy(*pattern_ast_ptr);
6520-
*pattern_ast_ptr = zend_ast_create_zval(&pattern_zv);
6521-
6522-
znode pattern_node;
6523-
pattern_node.op_type = IS_CONST;
6524-
ZVAL_COPY(&pattern_node.u.constant, &pattern_zv);
6525-
zend_op *op_data_op = &CG(active_op_array)->opcodes[op_data_opnum];
6526-
SET_NODE(op_data_op->op1, &pattern_node);
6527-
op_data_op->extended_value = pattern_context.binding_offset;
6528-
6529-
is_opline = &CG(active_op_array)->opcodes[is_opnum];
6530-
is_opline->extended_value = get_next_op_number();
6531-
6532-
if (pattern_context.binding_offset) {
6533-
zend_emit_op(NULL, ZEND_FREE, &bindings_node, NULL);
6534-
}
6535-
6536-
if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
6537-
// FIXME: Verify live ranges recognizes that OP1 needs to be freed if an exception occurs
6538-
zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
6539-
}
65406503
}
65416504

65426505
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)
68146777
pattern_context->inside_or_pattern = prev_inside_or_pattern;
68156778
}
68166779

6817-
static void zend_compile_is(znode *result, zend_ast *ast)
6780+
static uint32_t zend_emit_is(znode *result, znode *expr_node, zend_ast **pattern_ast_ptr)
68186781
{
6819-
zend_ast *expr_ast = ast->child[0];
6820-
zend_ast **pattern_ast_ptr = &ast->child[1];
6821-
6822-
znode expr_node;
6823-
zend_compile_expr(&expr_node, expr_ast);
6824-
68256782
znode bindings_node;
68266783
bindings_node.op_type = IS_TMP_VAR;
68276784
bindings_node.u.op.var = get_temporary_variable();
68286785

68296786
uint32_t is_opnum = get_next_op_number();
6830-
zend_emit_op_tmp(result, ZEND_IS, &expr_node, &bindings_node);
6787+
zend_emit_op_tmp(result, ZEND_IS, expr_node, &bindings_node);
68316788

68326789
uint32_t op_data_opnum = get_next_op_number();
68336790
zend_emit_op_data(NULL);
@@ -6854,6 +6811,19 @@ static void zend_compile_is(znode *result, zend_ast *ast)
68546811
zend_emit_op(NULL, ZEND_FREE, &bindings_node, NULL);
68556812
}
68566813

6814+
return is_opnum;
6815+
}
6816+
6817+
static void zend_compile_is(znode *result, zend_ast *ast)
6818+
{
6819+
zend_ast *expr_ast = ast->child[0];
6820+
zend_ast **pattern_ast_ptr = &ast->child[1];
6821+
6822+
znode expr_node;
6823+
zend_compile_expr(&expr_node, expr_ast);
6824+
6825+
zend_emit_is(result, &expr_node, pattern_ast_ptr);
6826+
68576827
if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
68586828
// FIXME: Verify live ranges recognizes that OP1 needs to be freed if an exception occurs
68596829
zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);

0 commit comments

Comments
 (0)