summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/opcache/Optimizer/optimize_func_calls.c7
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c57
2 files changed, 42 insertions, 22 deletions
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c
index 6f267df9b3..f9a42db79e 100644
--- a/ext/opcache/Optimizer/optimize_func_calls.c
+++ b/ext/opcache/Optimizer/optimize_func_calls.c
@@ -158,11 +158,11 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_FCALL:
+ case ZEND_NEW:
call_stack[call].func = zend_optimizer_get_called_func(
ctx->script, op_array, opline, 0);
- call_stack[call].try_inline = 1;
+ call_stack[call].try_inline = opline->opcode != ZEND_NEW;
/* break missing intentionally */
- case ZEND_NEW:
case ZEND_INIT_DYNAMIC_CALL:
case ZEND_INIT_USER_CALL:
call_stack[call].opline = opline;
@@ -194,7 +194,8 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
fcall->op2.constant = fcall->op2.constant + 1;
opline->opcode = zend_get_call_op(fcall, call_stack[call].func);
} else if (fcall->opcode == ZEND_INIT_STATIC_METHOD_CALL
- || fcall->opcode == ZEND_INIT_METHOD_CALL) {
+ || fcall->opcode == ZEND_INIT_METHOD_CALL
+ || fcall->opcode == ZEND_NEW) {
/* We don't have specialized opcodes for this, do nothing */
} else {
ZEND_ASSERT(0);
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index 82a6daa5ef..c88821e0e3 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -537,6 +537,33 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
return 1;
}
+static zend_class_entry *get_class_entry_from_op1(
+ zend_script *script, zend_op_array *op_array, zend_op *opline, zend_bool rt_constants) {
+ if (opline->op1_type == IS_CONST) {
+ zval *op1 = CRT_CONSTANT_EX(op_array, opline->op1, rt_constants);
+ if (Z_TYPE_P(op1) == IS_STRING) {
+ zend_string *class_name = Z_STR_P(op1 + 1);
+ zend_class_entry *ce;
+ if (script && (ce = zend_hash_find_ptr(&script->class_table, class_name))) {
+ return ce;
+ } else if ((ce = zend_hash_find_ptr(EG(class_table), class_name))) {
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ return ce;
+ } else if (ce->type == ZEND_USER_CLASS &&
+ ce->info.user.filename &&
+ ce->info.user.filename == op_array->filename) {
+ return ce;
+ }
+ }
+ }
+ } else if (opline->op1_type == IS_UNUSED && op_array->scope
+ && !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)
+ && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ return op_array->scope;
+ }
+ return NULL;
+}
+
zend_function *zend_optimizer_get_called_func(
zend_script *script, zend_op_array *op_array, zend_op *opline, zend_bool rt_constants)
{
@@ -579,25 +606,8 @@ zend_function *zend_optimizer_get_called_func(
break;
case ZEND_INIT_STATIC_METHOD_CALL:
if (opline->op2_type == IS_CONST && Z_TYPE_P(GET_OP(op2)) == IS_STRING) {
- zend_class_entry *ce = NULL;
- if (opline->op1_type == IS_CONST && Z_TYPE_P(GET_OP(op1)) == IS_STRING) {
- zend_string *class_name = Z_STR_P(GET_OP(op1) + 1);
- if (script && (ce = zend_hash_find_ptr(&script->class_table, class_name))) {
- /* pass */
- } else if ((ce = zend_hash_find_ptr(EG(class_table), class_name))) {
- if (ce->type == ZEND_INTERNAL_CLASS) {
- /* pass */
- } else if (ce->type != ZEND_USER_CLASS ||
- !ce->info.user.filename ||
- ce->info.user.filename != op_array->filename) {
- ce = NULL;
- }
- }
- } else if (opline->op1_type == IS_UNUSED && op_array->scope
- && !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)
- && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
- ce = op_array->scope;
- }
+ zend_class_entry *ce = get_class_entry_from_op1(
+ script, op_array, opline, rt_constants);
if (ce) {
zend_string *func_name = Z_STR_P(GET_OP(op2) + 1);
return zend_hash_find_ptr(&ce->function_table, func_name);
@@ -622,6 +632,15 @@ zend_function *zend_optimizer_get_called_func(
}
}
break;
+ case ZEND_NEW:
+ {
+ zend_class_entry *ce = get_class_entry_from_op1(
+ script, op_array, opline, rt_constants);
+ if (ce && ce->type == ZEND_USER_CLASS) {
+ return ce->constructor;
+ }
+ break;
+ }
}
return NULL;
#undef GET_OP