Skip to content

Commit ba9092a

Browse files
iluuu1994dstogov
andcommitted
Compile static frameless calls before emitting opcodes
Co-authored-by: Dmitry Stogov <[email protected]>
1 parent 9a64646 commit ba9092a

File tree

1 file changed

+36
-44
lines changed

1 file changed

+36
-44
lines changed

Zend/zend_compile.c

+36-44
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;
@@ -5343,29 +5336,11 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type
53435336
}
53445337
}
53455338

5346-
uint32_t init_opnum = get_next_op_number();
5347-
opline = get_next_op();
5348-
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
5349-
5350-
zend_set_class_name_op1(opline, &class_node);
5351-
5352-
if (method_node.op_type == IS_CONST) {
5353-
opline->op2_type = IS_CONST;
5354-
opline->op2.constant = zend_add_func_name_literal(
5355-
Z_STR(method_node.u.constant));
5356-
opline->result.num = zend_alloc_cache_slots(2);
5357-
} else {
5358-
if (opline->op1_type == IS_CONST) {
5359-
opline->result.num = zend_alloc_cache_slot();
5360-
}
5361-
SET_NODE(opline->op2, &method_node);
5362-
}
5363-
53645339
/* Check if we already know which method we're calling */
5365-
if (opline->op2_type == IS_CONST) {
5340+
if (method_node.op_type == IS_CONST) {
53665341
zend_class_entry *ce = NULL;
5367-
if (opline->op1_type == IS_CONST) {
5368-
zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op1) + 1);
5342+
if (class_node.op_type == IS_CONST) {
5343+
zend_string *lcname = zend_string_tolower(Z_STR(class_node.u.constant));
53695344
ce = zend_hash_find_ptr(CG(class_table), lcname);
53705345
if (ce) {
53715346
if (zend_compile_ignore_class(ce, CG(active_op_array)->filename)) {
@@ -5375,31 +5350,48 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type
53755350
&& zend_string_equals_ci(CG(active_class_entry)->name, lcname)) {
53765351
ce = CG(active_class_entry);
53775352
}
5378-
} else if (opline->op1_type == IS_UNUSED
5379-
&& (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
5353+
zend_string_release(lcname);
5354+
} else if (class_node.op_type == IS_UNUSED
5355+
&& (class_node.u.op.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
53805356
&& zend_is_scope_known()) {
53815357
ce = CG(active_class_entry);
53825358
}
53835359
if (ce) {
5384-
zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
5360+
zend_string *lcname = zend_string_tolower(Z_STR(method_node.u.constant));
53855361
fbc = zend_get_compatible_func_or_null(ce, lcname);
5362+
zend_string_release(lcname);
5363+
5364+
if (fbc
5365+
&& !(CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS)
5366+
&& (fbc->type == ZEND_INTERNAL_FUNCTION)
5367+
&& zend_ast_is_list(args_ast)
5368+
&& !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast))) {
5369+
if (zend_compile_frameless_icall(result, zend_ast_get_list(args_ast), fbc, type) != (uint32_t)-1) {
5370+
zval_ptr_dtor(&method_node.u.constant);
5371+
if (class_node.op_type == IS_CONST) {
5372+
zval_ptr_dtor(&class_node.u.constant);
5373+
}
5374+
return;
5375+
}
5376+
}
53865377
}
53875378
}
53885379

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

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

0 commit comments

Comments
 (0)