Skip to content

Commit b42f424

Browse files
committed
Implement ZEND_RECV_CE
1 parent 8376904 commit b42f424

16 files changed

+655
-571
lines changed

Zend/Optimizer/compact_literals.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
759759
Z_CACHE_SLOT_P(val) = op_array->cache_size;
760760
op_array->cache_size += sizeof(zval);
761761
}
762-
} else if (opline->opcode != ZEND_RECV) {
762+
} else if (opline->opcode != ZEND_RECV && opline->opcode != ZEND_RECV_CE) {
763763
break;
764764
}
765765
opline++;

Zend/Optimizer/dce.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ static inline bool may_have_side_effects(
176176
/* For now assume all calls have side effects */
177177
return 1;
178178
case ZEND_RECV:
179+
case ZEND_RECV_CE:
179180
case ZEND_RECV_INIT:
180181
/* Even though RECV_INIT can be side-effect free, these cannot be simply dropped
181182
* due to the prologue skipping code. */

Zend/Optimizer/zend_cfg.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc
7676
}
7777
if ((cfg->flags & ZEND_CFG_RECV_ENTRY)) {
7878
if (opcode == ZEND_RECV ||
79-
opcode == ZEND_RECV_INIT) {
79+
opcode == ZEND_RECV_INIT ||
80+
opcode == ZEND_RECV_CE) {
8081
succ->flags |= ZEND_BB_RECV_ENTRY;
8182
}
8283
}
@@ -292,6 +293,7 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array,
292293
zend_op *opline = op_array->opcodes + i;
293294
switch (opline->opcode) {
294295
case ZEND_RECV:
296+
case ZEND_RECV_CE:
295297
case ZEND_RECV_INIT:
296298
if (build_flags & ZEND_CFG_RECV_ENTRY) {
297299
BB_START(i + 1);

Zend/Optimizer/zend_dfg.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_
4141
}
4242
if ((build_flags & ZEND_SSA_USE_CV_RESULTS)
4343
&& opline->result_type == IS_CV
44-
&& opline->opcode != ZEND_RECV) {
44+
&& opline->opcode != ZEND_RECV
45+
&& opline->opcode != ZEND_RECV_CE) {
4546
var_num = EX_VAR_TO_NUM(opline->result.var);
4647
if (!zend_bitset_in(def, var_num)) {
4748
zend_bitset_incl(use, var_num);

Zend/Optimizer/zend_inference.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3300,6 +3300,7 @@ static zend_always_inline zend_result _zend_update_type_info(
33003300
UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RC1|MAY_BE_RCN, ssa_op->result_def);
33013301
break;
33023302
case ZEND_RECV:
3303+
case ZEND_RECV_CE:
33033304
case ZEND_RECV_INIT:
33043305
case ZEND_RECV_VARIADIC:
33053306
{
@@ -4759,6 +4760,7 @@ static void zend_mark_cv_references(const zend_op_array *op_array, const zend_sc
47594760
if (ssa->ops[def].result_def == var) {
47604761
switch (opline->opcode) {
47614762
case ZEND_RECV:
4763+
case ZEND_RECV_CE:
47624764
case ZEND_RECV_INIT:
47634765
arg_info = &op_array->arg_info[opline->op1.num-1];
47644766
if (!ZEND_ARG_SEND_MODE(arg_info)) {

Zend/Optimizer/zend_ssa.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,8 @@ static zend_always_inline int _zend_ssa_rename_op(const zend_op_array *op_array,
554554
}
555555
if ((build_flags & ZEND_SSA_USE_CV_RESULTS)
556556
&& opline->result_type == IS_CV
557-
&& opline->opcode != ZEND_RECV) {
557+
&& opline->opcode != ZEND_RECV
558+
&& opline->opcode != ZEND_RECV_CE) {
558559
ssa_ops[k].result_use = var[EX_VAR_TO_NUM(opline->result.var)];
559560
//USE_SSA_VAR(op_array->last_var + opline->result.var)
560561
}

Zend/zend_compile.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7747,13 +7747,28 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
77477747
zval_ptr_dtor(&default_node.u.constant);
77487748
}
77497749

7750-
opline = zend_emit_op(NULL, opcode, NULL, &default_node);
7751-
SET_NODE(opline->result, &var_node);
7752-
opline->op1.num = i + 1;
7753-
77547750
uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
77557751
| (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0);
77567752
ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;
7753+
7754+
if (opcode == ZEND_RECV
7755+
&& type_ast
7756+
&& ZEND_TYPE_IS_COMPLEX(arg_info->type)
7757+
&& !ZEND_TYPE_HAS_LIST(arg_info->type)
7758+
&& ZEND_TYPE_HAS_NAME(arg_info->type)
7759+
&& !ZEND_TYPE_HAS_LITERAL_NAME(arg_info->type) // TODO: necessary?
7760+
&& ZEND_TYPE_PURE_MASK(arg_info->type) == 0) {
7761+
znode ce_name;
7762+
ce_name.op_type = IS_CONST;
7763+
ZVAL_STR_COPY(&ce_name.u.constant, ZEND_TYPE_NAME(arg_info->type));
7764+
opcode = ZEND_RECV_CE;
7765+
opline = zend_emit_op(NULL, opcode, NULL, &ce_name);
7766+
} else {
7767+
opline = zend_emit_op(NULL, opcode, NULL, &default_node);
7768+
}
7769+
SET_NODE(opline->result, &var_node);
7770+
opline->op1.num = i + 1;
7771+
77577772
if (opcode == ZEND_RECV) {
77587773
opline->op2.num = type_ast ?
77597774
ZEND_TYPE_FULL_MASK(arg_info->type) : MAY_BE_ANY;

Zend/zend_execute.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,10 +1099,9 @@ static zend_always_inline bool zend_value_instanceof_static(const zval *zv) {
10991099
return instanceof_function(Z_OBJCE_P(zv), called_scope);
11001100
}
11011101

1102-
static zend_always_inline zend_class_entry *zend_fetch_ce_from_type(
1103-
const zend_type *type)
1102+
static zend_always_inline zend_class_entry *zend_fetch_ce_from_type_name(
1103+
zend_string *name)
11041104
{
1105-
zend_string *name = ZEND_TYPE_NAME(*type);
11061105
zend_class_entry *ce;
11071106
if (ZSTR_HAS_CE_CACHE(name)) {
11081107
ce = ZSTR_GET_CE_CACHE(name);
@@ -1123,6 +1122,13 @@ static zend_always_inline zend_class_entry *zend_fetch_ce_from_type(
11231122
return ce;
11241123
}
11251124

1125+
static zend_always_inline zend_class_entry *zend_fetch_ce_from_type(
1126+
const zend_type *type)
1127+
{
1128+
zend_string *name = ZEND_TYPE_NAME(*type);
1129+
return zend_fetch_ce_from_type_name(name);
1130+
}
1131+
11261132
static bool zend_check_intersection_type_from_list(
11271133
const zend_type_list *intersection_type_list,
11281134
zend_class_entry *arg_ce)
@@ -5510,7 +5516,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *cal
55105516
ZVAL_COPY(arg, default_value);
55115517
}
55125518
} else {
5513-
ZEND_ASSERT(opline->opcode == ZEND_RECV);
5519+
ZEND_ASSERT(opline->opcode == ZEND_RECV);//TODO
55145520
zend_execute_data *old = start_fake_frame(call, opline);
55155521
zend_argument_error(zend_ce_argument_count_error, i + 1, "not passed");
55165522
end_fake_frame(call, old);

Zend/zend_inheritance.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration(
977977

978978
++idx;
979979
while (op < end) {
980-
if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
980+
if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT || op->opcode == ZEND_RECV_CE)
981981
&& op->op1.num == (zend_ulong)idx)
982982
{
983983
precv = op;

Zend/zend_vm_def.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5695,6 +5695,28 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED)
56955695
ZEND_VM_NEXT_OPCODE();
56965696
}
56975697

5698+
ZEND_VM_HOT_HANDLER(210, ZEND_RECV_CE, NUM, CONST)
5699+
{
5700+
USE_OPLINE
5701+
uint32_t arg_num = opline->op1.num;
5702+
zend_string *ce_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5703+
zval *param;
5704+
zend_class_entry *ce;
5705+
5706+
if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
5707+
ZEND_VM_DISPATCH_TO_HELPER(zend_missing_arg_helper);
5708+
}
5709+
5710+
param = EX_VAR(opline->result.var);
5711+
// fprintf(stderr,"ce_name=%s %x\n", ZSTR_VAL(ce_name), ZSTR_GET_CE_CACHE(ce_name));
5712+
5713+
if (EXPECTED(Z_TYPE_P(param) == IS_OBJECT && (ce = zend_fetch_ce_from_type_name(ce_name)) && instanceof_function(Z_OBJCE_P(param), ce))) {
5714+
ZEND_VM_NEXT_OPCODE();
5715+
} else {
5716+
ZEND_VM_DISPATCH_TO_HELPER(zend_verify_recv_arg_type_helper, op_1, param);
5717+
}
5718+
}
5719+
56985720
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NOTYPE, NUM, NUM)
56995721
{
57005722
USE_OPLINE

0 commit comments

Comments
 (0)