Skip to content

Commit 3c8beb1

Browse files
committed
Allow early-binding of ZEND_NEW args
1 parent 8106c01 commit 3c8beb1

File tree

2 files changed

+42
-22
lines changed

2 files changed

+42
-22
lines changed

ext/opcache/Optimizer/optimize_func_calls.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
158158
case ZEND_INIT_STATIC_METHOD_CALL:
159159
case ZEND_INIT_METHOD_CALL:
160160
case ZEND_INIT_FCALL:
161+
case ZEND_NEW:
161162
call_stack[call].func = zend_optimizer_get_called_func(
162163
ctx->script, op_array, opline, 0);
163-
call_stack[call].try_inline = 1;
164+
call_stack[call].try_inline = opline->opcode != ZEND_NEW;
164165
/* break missing intentionally */
165-
case ZEND_NEW:
166166
case ZEND_INIT_DYNAMIC_CALL:
167167
case ZEND_INIT_USER_CALL:
168168
call_stack[call].opline = opline;
@@ -194,7 +194,8 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
194194
fcall->op2.constant = fcall->op2.constant + 1;
195195
opline->opcode = zend_get_call_op(fcall, call_stack[call].func);
196196
} else if (fcall->opcode == ZEND_INIT_STATIC_METHOD_CALL
197-
|| fcall->opcode == ZEND_INIT_METHOD_CALL) {
197+
|| fcall->opcode == ZEND_INIT_METHOD_CALL
198+
|| fcall->opcode == ZEND_NEW) {
198199
/* We don't have specialized opcodes for this, do nothing */
199200
} else {
200201
ZEND_ASSERT(0);

ext/opcache/Optimizer/zend_optimizer.c

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,33 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
537537
return 1;
538538
}
539539

540+
static zend_class_entry *get_class_entry_from_op1(
541+
zend_script *script, zend_op_array *op_array, zend_op *opline, zend_bool rt_constants) {
542+
if (opline->op1_type == IS_CONST) {
543+
zval *op1 = CRT_CONSTANT_EX(op_array, opline->op1, rt_constants);
544+
if (Z_TYPE_P(op1) == IS_STRING) {
545+
zend_string *class_name = Z_STR_P(op1 + 1);
546+
zend_class_entry *ce;
547+
if (script && (ce = zend_hash_find_ptr(&script->class_table, class_name))) {
548+
return ce;
549+
} else if ((ce = zend_hash_find_ptr(EG(class_table), class_name))) {
550+
if (ce->type == ZEND_INTERNAL_CLASS) {
551+
return ce;
552+
} else if (ce->type == ZEND_USER_CLASS &&
553+
ce->info.user.filename &&
554+
ce->info.user.filename == op_array->filename) {
555+
return ce;
556+
}
557+
}
558+
}
559+
} else if (opline->op1_type == IS_UNUSED && op_array->scope
560+
&& !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)
561+
&& (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
562+
return op_array->scope;
563+
}
564+
return NULL;
565+
}
566+
540567
zend_function *zend_optimizer_get_called_func(
541568
zend_script *script, zend_op_array *op_array, zend_op *opline, zend_bool rt_constants)
542569
{
@@ -579,25 +606,8 @@ zend_function *zend_optimizer_get_called_func(
579606
break;
580607
case ZEND_INIT_STATIC_METHOD_CALL:
581608
if (opline->op2_type == IS_CONST && Z_TYPE_P(GET_OP(op2)) == IS_STRING) {
582-
zend_class_entry *ce = NULL;
583-
if (opline->op1_type == IS_CONST && Z_TYPE_P(GET_OP(op1)) == IS_STRING) {
584-
zend_string *class_name = Z_STR_P(GET_OP(op1) + 1);
585-
if (script && (ce = zend_hash_find_ptr(&script->class_table, class_name))) {
586-
/* pass */
587-
} else if ((ce = zend_hash_find_ptr(EG(class_table), class_name))) {
588-
if (ce->type == ZEND_INTERNAL_CLASS) {
589-
/* pass */
590-
} else if (ce->type != ZEND_USER_CLASS ||
591-
!ce->info.user.filename ||
592-
ce->info.user.filename != op_array->filename) {
593-
ce = NULL;
594-
}
595-
}
596-
} else if (opline->op1_type == IS_UNUSED && op_array->scope
597-
&& !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)
598-
&& (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
599-
ce = op_array->scope;
600-
}
609+
zend_class_entry *ce = get_class_entry_from_op1(
610+
script, op_array, opline, rt_constants);
601611
if (ce) {
602612
zend_string *func_name = Z_STR_P(GET_OP(op2) + 1);
603613
return zend_hash_find_ptr(&ce->function_table, func_name);
@@ -622,6 +632,15 @@ zend_function *zend_optimizer_get_called_func(
622632
}
623633
}
624634
break;
635+
case ZEND_NEW:
636+
{
637+
zend_class_entry *ce = get_class_entry_from_op1(
638+
script, op_array, opline, rt_constants);
639+
if (ce && ce->type == ZEND_USER_CLASS) {
640+
return ce->constructor;
641+
}
642+
break;
643+
}
625644
}
626645
return NULL;
627646
#undef GET_OP

0 commit comments

Comments
 (0)