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) {
case ZEND_INIT_ARRAY:
return 1;
case ZEND_NEW:
case ZEND_NEW: {
/* objects with destructors should escape */
if (opline->op1_type == IS_CONST) {
zend_class_entry *ce = zend_optimizer_get_class_entry(
script, op_array, Z_STR_P(CRT_CONSTANT(opline->op1)+1));
uint32_t forbidden_flags =
/* These flags will always cause an exception */
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
| ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
if (ce && !ce->parent && !ce->create_object && !ce->constructor &&
!ce->destructor && !ce->__get && !ce->__set &&
!(ce->ce_flags & forbidden_flags) &&
(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
return 1;
}
zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
script, op_array, opline);
uint32_t forbidden_flags =
/* These flags will always cause an exception */
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
| ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
if (ce && !ce->parent && !ce->create_object && !ce->constructor &&
!ce->destructor && !ce->__get && !ce->__set &&
!(ce->ce_flags & forbidden_flags) &&
(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
return 1;
}
break;
}
case ZEND_QM_ASSIGN:
if (opline->op1_type == IS_CONST
&& 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_ASSIGN:
return 1;
case ZEND_NEW:
case ZEND_NEW: {
/* objects with destructors should escape */
if (opline->op1_type == IS_CONST) {
zend_class_entry *ce = zend_optimizer_get_class_entry(
script, op_array, Z_STR_P(CRT_CONSTANT(opline->op1)+1));
if (ce && !ce->create_object && !ce->constructor &&
!ce->destructor && !ce->__get && !ce->__set && !ce->parent) {
return 1;
}
zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
script, op_array, opline);
if (ce && !ce->create_object && !ce->constructor &&
!ce->destructor && !ce->__get && !ce->__set && !ce->parent) {
return 1;
}
break;
}
}
} else if (op->op1_def == var) {
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 &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
zend_class_entry *ce = NULL;
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;
}
zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
ctx->script, op_array, opline);
if (ce) {
zend_class_constant *cc;
zval *c, t;

View file

@ -3027,8 +3027,8 @@ static zend_always_inline zend_result _zend_update_type_info(
break;
case ZEND_NEW:
tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT;
if (opline->op1_type == IS_CONST &&
(ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(CRT_CONSTANT(opline->op1)+1))) != NULL) {
ce = zend_optimizer_get_class_entry_from_op1(script, op_array, opline);
if (ce) {
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) {
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;
}
static zend_class_entry *get_class_entry_from_op1(
zend_script *script, zend_op_array *op_array, zend_op *opline) {
zend_class_entry *zend_optimizer_get_class_entry_from_op1(
const zend_script *script, const zend_op_array *op_array, const zend_op *opline) {
if (opline->op1_type == IS_CONST) {
zval *op1 = CRT_CONSTANT(opline->op1);
if (Z_TYPE_P(op1) == IS_STRING) {
@ -770,7 +770,7 @@ zend_function *zend_optimizer_get_called_func(
break;
case ZEND_INIT_STATIC_METHOD_CALL:
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);
if (ce) {
zend_string *func_name = Z_STR_P(CRT_CONSTANT(opline->op2) + 1);
@ -812,7 +812,7 @@ zend_function *zend_optimizer_get_called_func(
break;
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);
if (ce && ce->type == ZEND_USER_CLASS) {
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_class_entry *zend_optimizer_get_class_entry(
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_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx);