Skip to content

Commit 466e7a4

Browse files
iluuu1994dstogov
andcommitted
Compile static frameless calls before emitting opcodes
Co-authored-by: Dmitry Stogov <[email protected]>
1 parent 7be62b7 commit 466e7a4

File tree

1 file changed

+36
-44
lines changed

1 file changed

+36
-44
lines changed

Zend/zend_compile.c

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,6 @@
5959

6060
#define FC(member) (CG(file_context).member)
6161

62-
#define ZEND_OP1_LITERAL(opline) (op_array)->literals[(opline)->op1.constant]
63-
#define ZEND_OP2_LITERAL(opline) (op_array)->literals[(opline)->op2.constant]
64-
#define literal_dtor(zv) do { \
65-
zval_ptr_dtor_nogc(zv); \
66-
ZVAL_NULL(zv); \
67-
} while (0)
68-
6962
typedef struct _zend_loop_var {
7063
uint8_t opcode;
7164
uint8_t var_type;
@@ -5336,29 +5329,11 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type
53365329
}
53375330
}
53385331

5339-
uint32_t init_opnum = get_next_op_number();
5340-
opline = get_next_op();
5341-
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
5342-
5343-
zend_set_class_name_op1(opline, &class_node);
5344-
5345-
if (method_node.op_type == IS_CONST) {
5346-
opline->op2_type = IS_CONST;
5347-
opline->op2.constant = zend_add_func_name_literal(
5348-
Z_STR(method_node.u.constant));
5349-
opline->result.num = zend_alloc_cache_slots(2);
5350-
} else {
5351-
if (opline->op1_type == IS_CONST) {
5352-
opline->result.num = zend_alloc_cache_slot();
5353-
}
5354-
SET_NODE(opline->op2, &method_node);
5355-
}
5356-
53575332
/* Check if we already know which method we're calling */
5358-
if (opline->op2_type == IS_CONST) {
5333+
if (method_node.op_type == IS_CONST) {
53595334
zend_class_entry *ce = NULL;
5360-
if (opline->op1_type == IS_CONST) {
5361-
zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op1) + 1);
5335+
if (class_node.op_type == IS_CONST) {
5336+
zend_string *lcname = zend_string_tolower(Z_STR(class_node.u.constant));
53625337
ce = zend_hash_find_ptr(CG(class_table), lcname);
53635338
if (ce) {
53645339
if (zend_compile_ignore_class(ce, CG(active_op_array)->filename)) {
@@ -5368,31 +5343,48 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type
53685343
&& zend_string_equals_ci(CG(active_class_entry)->name, lcname)) {
53695344
ce = CG(active_class_entry);
53705345
}
5371-
} else if (opline->op1_type == IS_UNUSED
5372-
&& (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
5346+
zend_string_release(lcname);
5347+
} else if (class_node.op_type == IS_UNUSED
5348+
&& (class_node.u.op.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
53735349
&& zend_is_scope_known()) {
53745350
ce = CG(active_class_entry);
53755351
}
53765352
if (ce) {
5377-
zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
5353+
zend_string *lcname = zend_string_tolower(Z_STR(method_node.u.constant));
53785354
fbc = zend_get_compatible_func_or_null(ce, lcname);
5355+
zend_string_release(lcname);
5356+
5357+
if (fbc
5358+
&& !(CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS)
5359+
&& (fbc->type == ZEND_INTERNAL_FUNCTION)
5360+
&& zend_ast_is_list(args_ast)
5361+
&& !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast))) {
5362+
if (zend_compile_frameless_icall(result, zend_ast_get_list(args_ast), fbc, type) != (uint32_t)-1) {
5363+
zval_ptr_dtor(&method_node.u.constant);
5364+
if (class_node.op_type == IS_CONST) {
5365+
zval_ptr_dtor(&class_node.u.constant);
5366+
}
5367+
return;
5368+
}
5369+
}
53795370
}
53805371
}
53815372

5382-
if (!(CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS)
5383-
&& fbc
5384-
&& (fbc->type == ZEND_INTERNAL_FUNCTION)
5385-
&& zend_ast_is_list(args_ast)
5386-
&& !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast))) {
5387-
if (zend_compile_frameless_icall(result, zend_ast_get_list(args_ast), fbc, type) != (uint32_t)-1) {
5388-
/* Update opline in case it got invalidated. */
5389-
zend_op_array *op_array = CG(active_op_array);
5390-
opline = &op_array->opcodes[init_opnum];
5391-
literal_dtor(&ZEND_OP1_LITERAL(opline));
5392-
literal_dtor(&ZEND_OP2_LITERAL(opline));
5393-
MAKE_NOP(opline);
5394-
return;
5373+
opline = get_next_op();
5374+
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
5375+
5376+
zend_set_class_name_op1(opline, &class_node);
5377+
5378+
if (method_node.op_type == IS_CONST) {
5379+
opline->op2_type = IS_CONST;
5380+
opline->op2.constant = zend_add_func_name_literal(
5381+
Z_STR(method_node.u.constant));
5382+
opline->result.num = zend_alloc_cache_slots(2);
5383+
} else {
5384+
if (opline->op1_type == IS_CONST) {
5385+
opline->result.num = zend_alloc_cache_slot();
53955386
}
5387+
SET_NODE(opline->op2, &method_node);
53965388
}
53975389

53985390
zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast));

0 commit comments

Comments
 (0)