diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index 1f846959bc0..0218a77d3f9 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -293,7 +293,7 @@ static inline bool can_elide_return_type_check( ZEND_TYPE_FOREACH(arg_info->type, single_type) { if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(*single_type)); - zend_class_entry *ce = zend_optimizer_get_class_entry(script, lcname); + zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname); zend_string_release(lcname); bool result = ce && safe_instanceof(use_info->ce, ce); if (result == !is_intersection) { diff --git a/Zend/Optimizer/escape_analysis.c b/Zend/Optimizer/escape_analysis.c index e13015ceb7c..e66fc4f9e71 100644 --- a/Zend/Optimizer/escape_analysis.c +++ b/Zend/Optimizer/escape_analysis.c @@ -160,7 +160,7 @@ static bool is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, i /* objects with destructors should escape */ if (opline->op1_type == IS_CONST) { zend_class_entry *ce = zend_optimizer_get_class_entry( - script, Z_STR_P(CRT_CONSTANT(opline->op1)+1)); + 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 @@ -228,7 +228,7 @@ static bool is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int va /* objects with destructors should escape */ if (opline->op1_type == IS_CONST) { zend_class_entry *ce = zend_optimizer_get_class_entry( - script, Z_STR_P(CRT_CONSTANT(opline->op1)+1)); + 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; diff --git a/Zend/Optimizer/pass1.c b/Zend/Optimizer/pass1.c index b330ca24b4d..1aad01cb2f1 100644 --- a/Zend/Optimizer/pass1.c +++ b/Zend/Optimizer/pass1.c @@ -179,15 +179,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) if (opline->op1_type == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { /* for A::B */ - if (op_array->scope && - zend_string_equals_ci(Z_STR(ZEND_OP1_LITERAL(opline)), op_array->scope->name)) { - ce = op_array->scope; - } else { - ce = zend_optimizer_get_class_entry( - ctx->script, Z_STR(op_array->literals[opline->op1.constant + 1])); - if (!ce) { - break; - } + 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 && diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 52d093db116..c7df495c0ae 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2143,7 +2143,8 @@ static uint32_t zend_convert_type(const zend_script *script, zend_type type, zen * we use a plain object type for class unions. */ if (ZEND_TYPE_HAS_NAME(type)) { zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(type)); - *pce = zend_optimizer_get_class_entry(script, lcname); + // TODO: Pass through op_array. + *pce = zend_optimizer_get_class_entry(script, NULL, lcname); zend_string_release_ex(lcname, 0); } } @@ -2231,7 +2232,7 @@ static zend_property_info *zend_fetch_static_prop_info(const zend_script *script } } else if (opline->op2_type == IS_CONST) { zval *zv = CRT_CONSTANT(opline->op2); - ce = zend_optimizer_get_class_entry(script, Z_STR_P(zv + 1)); + ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(zv + 1)); } if (ce) { @@ -3015,7 +3016,7 @@ static zend_always_inline zend_result _zend_update_type_info( } else if (opline->op2_type == IS_CONST) { zval *zv = CRT_CONSTANT(opline->op2); if (Z_TYPE_P(zv) == IS_STRING) { - ce = zend_optimizer_get_class_entry(script, Z_STR_P(zv+1)); + ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(zv+1)); UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_op->result_def); } else { UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def); @@ -3027,7 +3028,7 @@ static zend_always_inline zend_result _zend_update_type_info( 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, Z_STR_P(CRT_CONSTANT(opline->op1)+1))) != NULL) { + (ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(CRT_CONSTANT(opline->op1)+1))) != NULL) { 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); diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index 9de7a944da1..1abeeefeaca 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -694,7 +694,8 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_ } } -zend_class_entry *zend_optimizer_get_class_entry(const zend_script *script, zend_string *lcname) { +zend_class_entry *zend_optimizer_get_class_entry( + const zend_script *script, const zend_op_array *op_array, zend_string *lcname) { zend_class_entry *ce = script ? zend_hash_find_ptr(&script->class_table, lcname) : NULL; if (ce) { return ce; @@ -705,6 +706,10 @@ zend_class_entry *zend_optimizer_get_class_entry(const zend_script *script, zend return ce; } + if (op_array && op_array->scope && zend_string_equals_ci(op_array->scope->name, lcname)) { + return op_array->scope; + } + return NULL; } @@ -713,7 +718,7 @@ static zend_class_entry *get_class_entry_from_op1( if (opline->op1_type == IS_CONST) { zval *op1 = CRT_CONSTANT(opline->op1); if (Z_TYPE_P(op1) == IS_STRING) { - return zend_optimizer_get_class_entry(script, Z_STR_P(op1 + 1)); + return zend_optimizer_get_class_entry(script, op_array, Z_STR_P(op1 + 1)); } } else if (opline->op1_type == IS_UNUSED && op_array->scope && !(op_array->scope->ce_flags & ZEND_ACC_TRAIT) diff --git a/Zend/Optimizer/zend_optimizer_internal.h b/Zend/Optimizer/zend_optimizer_internal.h index bd4367eaf27..550b911052a 100644 --- a/Zend/Optimizer/zend_optimizer_internal.h +++ b/Zend/Optimizer/zend_optimizer_internal.h @@ -96,7 +96,8 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array, uint32_t var, zval *val); 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, zend_string *lcname); +zend_class_entry *zend_optimizer_get_class_entry( + const zend_script *script, const zend_op_array *op_array, zend_string *lcname); 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); diff --git a/Zend/Optimizer/zend_ssa.c b/Zend/Optimizer/zend_ssa.c index 9ca2e11a6f7..98f60468a0e 100644 --- a/Zend/Optimizer/zend_ssa.c +++ b/Zend/Optimizer/zend_ssa.c @@ -527,7 +527,7 @@ static void place_essa_pis( (opline-1)->op2_type == IS_CONST) { int var = EX_VAR_TO_NUM((opline-1)->op1.var); zend_string *lcname = Z_STR_P(CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op2) + 1); - zend_class_entry *ce = zend_optimizer_get_class_entry(script, lcname); + zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname); if (!ce) { continue; }