Reuse get_class_entry_from_op1() helper

Export and reuse this helper in places that fetch a class entry
from op1.
This commit is contained in:
Nikita Popov 2021-12-25 22:18:50 +01:00
parent 2cf93032ee
commit 206d80e11a
5 changed files with 30 additions and 45 deletions

View file

@ -156,23 +156,22 @@ static bool is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, i
switch (opline->opcode) { switch (opline->opcode) {
case ZEND_INIT_ARRAY: case ZEND_INIT_ARRAY:
return 1; return 1;
case ZEND_NEW: case ZEND_NEW: {
/* objects with destructors should escape */ /* objects with destructors should escape */
if (opline->op1_type == IS_CONST) { zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
zend_class_entry *ce = zend_optimizer_get_class_entry( script, op_array, opline);
script, op_array, Z_STR_P(CRT_CONSTANT(opline->op1)+1)); uint32_t forbidden_flags =
uint32_t forbidden_flags = /* These flags will always cause an exception */
/* These flags will always cause an exception */ ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
| ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT; if (ce && !ce->parent && !ce->create_object && !ce->constructor &&
if (ce && !ce->parent && !ce->create_object && !ce->constructor && !ce->destructor && !ce->__get && !ce->__set &&
!ce->destructor && !ce->__get && !ce->__set && !(ce->ce_flags & forbidden_flags) &&
!(ce->ce_flags & forbidden_flags) && (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { return 1;
return 1;
}
} }
break; break;
}
case ZEND_QM_ASSIGN: case ZEND_QM_ASSIGN:
if (opline->op1_type == IS_CONST if (opline->op1_type == IS_CONST
&& Z_TYPE_P(CRT_CONSTANT(opline->op1)) == IS_ARRAY) { && Z_TYPE_P(CRT_CONSTANT(opline->op1)) == IS_ARRAY) {
@ -224,17 +223,16 @@ static bool is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int va
case ZEND_QM_ASSIGN: case ZEND_QM_ASSIGN:
case ZEND_ASSIGN: case ZEND_ASSIGN:
return 1; return 1;
case ZEND_NEW: case ZEND_NEW: {
/* objects with destructors should escape */ /* objects with destructors should escape */
if (opline->op1_type == IS_CONST) { zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
zend_class_entry *ce = zend_optimizer_get_class_entry( script, op_array, opline);
script, op_array, Z_STR_P(CRT_CONSTANT(opline->op1)+1)); if (ce && !ce->create_object && !ce->constructor &&
if (ce && !ce->create_object && !ce->constructor && !ce->destructor && !ce->__get && !ce->__set && !ce->parent) {
!ce->destructor && !ce->__get && !ce->__set && !ce->parent) { return 1;
return 1;
}
} }
break; break;
}
} }
} else if (op->op1_def == var) { } else if (op->op1_def == var) {
switch (opline->opcode) { switch (opline->opcode) {

View file

@ -174,23 +174,8 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
if (opline->op2_type == IS_CONST && if (opline->op2_type == IS_CONST &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
zend_class_entry *ce = NULL; zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
ctx->script, op_array, opline);
if (opline->op1_type == IS_CONST &&
Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
/* for A::B */
ce = zend_optimizer_get_class_entry(
ctx->script, op_array, Z_STR(op_array->literals[opline->op1.constant + 1]));
if (!ce) {
break;
}
} else if (op_array->scope &&
opline->op1_type == IS_UNUSED &&
(opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
/* for self::B */
ce = op_array->scope;
}
if (ce) { if (ce) {
zend_class_constant *cc; zend_class_constant *cc;
zval *c, t; zval *c, t;

View file

@ -3027,8 +3027,8 @@ static zend_always_inline zend_result _zend_update_type_info(
break; break;
case ZEND_NEW: case ZEND_NEW:
tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT; tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT;
if (opline->op1_type == IS_CONST && ce = zend_optimizer_get_class_entry_from_op1(script, op_array, opline);
(ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(CRT_CONSTANT(opline->op1)+1))) != NULL) { if (ce) {
UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_op->result_def); UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_op->result_def);
} else if ((t1 & MAY_BE_CLASS) && ssa_op->op1_use >= 0 && ssa_var_info[ssa_op->op1_use].ce) { } else if ((t1 & MAY_BE_CLASS) && ssa_op->op1_use >= 0 && ssa_var_info[ssa_op->op1_use].ce) {
UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_op->op1_use].ce, ssa_var_info[ssa_op->op1_use].is_instanceof, ssa_op->result_def); UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_op->op1_use].ce, ssa_var_info[ssa_op->op1_use].is_instanceof, ssa_op->result_def);

View file

@ -713,8 +713,8 @@ zend_class_entry *zend_optimizer_get_class_entry(
return NULL; return NULL;
} }
static zend_class_entry *get_class_entry_from_op1( zend_class_entry *zend_optimizer_get_class_entry_from_op1(
zend_script *script, zend_op_array *op_array, zend_op *opline) { const zend_script *script, const zend_op_array *op_array, const zend_op *opline) {
if (opline->op1_type == IS_CONST) { if (opline->op1_type == IS_CONST) {
zval *op1 = CRT_CONSTANT(opline->op1); zval *op1 = CRT_CONSTANT(opline->op1);
if (Z_TYPE_P(op1) == IS_STRING) { if (Z_TYPE_P(op1) == IS_STRING) {
@ -770,7 +770,7 @@ zend_function *zend_optimizer_get_called_func(
break; break;
case ZEND_INIT_STATIC_METHOD_CALL: case ZEND_INIT_STATIC_METHOD_CALL:
if (opline->op2_type == IS_CONST && Z_TYPE_P(CRT_CONSTANT(opline->op2)) == IS_STRING) { if (opline->op2_type == IS_CONST && Z_TYPE_P(CRT_CONSTANT(opline->op2)) == IS_STRING) {
zend_class_entry *ce = get_class_entry_from_op1( zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
script, op_array, opline); script, op_array, opline);
if (ce) { if (ce) {
zend_string *func_name = Z_STR_P(CRT_CONSTANT(opline->op2) + 1); zend_string *func_name = Z_STR_P(CRT_CONSTANT(opline->op2) + 1);
@ -812,7 +812,7 @@ zend_function *zend_optimizer_get_called_func(
break; break;
case ZEND_NEW: case ZEND_NEW:
{ {
zend_class_entry *ce = get_class_entry_from_op1( zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
script, op_array, opline); script, op_array, opline);
if (ce && ce->type == ZEND_USER_CLASS) { if (ce && ce->type == ZEND_USER_CLASS) {
return ce->constructor; return ce->constructor;

View file

@ -98,6 +98,8 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array,
zend_op *zend_optimizer_get_loop_var_def(const zend_op_array *op_array, zend_op *free_opline); zend_op *zend_optimizer_get_loop_var_def(const zend_op_array *op_array, zend_op *free_opline);
zend_class_entry *zend_optimizer_get_class_entry( zend_class_entry *zend_optimizer_get_class_entry(
const zend_script *script, const zend_op_array *op_array, zend_string *lcname); const zend_script *script, const zend_op_array *op_array, zend_string *lcname);
zend_class_entry *zend_optimizer_get_class_entry_from_op1(
const zend_script *script, const zend_op_array *op_array, const zend_op *opline);
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx);
void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx);