From: Nikita Popov Date: Thu, 10 Nov 2016 21:51:39 +0000 (+0100) Subject: Allow early-binding of ZEND_NEW args X-Git-Tag: php-7.2.0alpha1~955^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3c8beb16c4a127b4fea0a5b5d9e853f4e41dbbd7;p=php Allow early-binding of ZEND_NEW args --- 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