mirror of
https://github.com/php/php-src.git
synced 2024-09-22 18:37:25 +00:00
Allow optional ignorance of operator overlaoding. Optimizer takes into account possibility of operator overloading at default optimization level, but ignores this possibility at "unsafe" level (opcache.optimization_level=-1).
This commit is contained in:
parent
298de027d6
commit
a02a126d54
@ -110,7 +110,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx,
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (zend_ssa_inference(&ctx->arena, op_array, ctx->script, ssa) != SUCCESS) {
|
||||
if (zend_ssa_inference(&ctx->arena, op_array, ctx->script, ssa, ctx->optimization_level) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
@ -2092,17 +2092,20 @@ static uint32_t assign_dim_result_type(
|
||||
|
||||
/* For binary ops that have compound assignment operators */
|
||||
static uint32_t binary_op_result_type(
|
||||
zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, uint32_t result_var) {
|
||||
zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, uint32_t result_var,
|
||||
zend_long optimization_level) {
|
||||
uint32_t tmp = 0;
|
||||
uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
|
||||
uint32_t t2_type = (t2 & MAY_BE_ANY) | (t2 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
|
||||
|
||||
if (!(ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level)) {
|
||||
/* Handle potentially overloaded operators.
|
||||
* This could be made more precise by checking the class type, if known. */
|
||||
if ((t1_type & MAY_BE_OBJECT) || (t2_type & MAY_BE_OBJECT)) {
|
||||
/* This is somewhat GMP specific. */
|
||||
tmp |= MAY_BE_OBJECT | MAY_BE_FALSE | MAY_BE_RC1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case ZEND_ADD:
|
||||
@ -2158,7 +2161,11 @@ static uint32_t binary_op_result_type(
|
||||
* handling */
|
||||
break;
|
||||
case ZEND_MOD:
|
||||
if (ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level) {
|
||||
tmp = MAY_BE_LONG;
|
||||
} else {
|
||||
tmp |= MAY_BE_LONG;
|
||||
}
|
||||
/* Division by zero results in an exception, so it doesn't need any special handling */
|
||||
break;
|
||||
case ZEND_BW_OR:
|
||||
@ -2173,7 +2180,11 @@ static uint32_t binary_op_result_type(
|
||||
break;
|
||||
case ZEND_SL:
|
||||
case ZEND_SR:
|
||||
if (ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level) {
|
||||
tmp = MAY_BE_LONG;
|
||||
} else {
|
||||
tmp |= MAY_BE_LONG;
|
||||
}
|
||||
break;
|
||||
case ZEND_CONCAT:
|
||||
case ZEND_FAST_CONCAT:
|
||||
@ -2240,7 +2251,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
|
||||
zend_ssa *ssa,
|
||||
const zend_script *script,
|
||||
zend_bitset worklist,
|
||||
int i)
|
||||
int i,
|
||||
zend_long optimization_level)
|
||||
{
|
||||
uint32_t t1, t2;
|
||||
uint32_t tmp, orig;
|
||||
@ -2290,7 +2302,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
|
||||
case ZEND_SL:
|
||||
case ZEND_SR:
|
||||
case ZEND_CONCAT:
|
||||
tmp = binary_op_result_type(ssa, opline->opcode, t1, t2, ssa_ops[i].result_def);
|
||||
tmp = binary_op_result_type(ssa, opline->opcode, t1, t2, ssa_ops[i].result_def, optimization_level);
|
||||
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
|
||||
break;
|
||||
case ZEND_BW_NOT:
|
||||
@ -2301,10 +2313,12 @@ static int zend_update_type_info(const zend_op_array *op_array,
|
||||
if (t1 & (MAY_BE_ANY-MAY_BE_STRING)) {
|
||||
tmp |= MAY_BE_LONG;
|
||||
}
|
||||
if (!(ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level)) {
|
||||
if (t1 & MAY_BE_OBJECT) {
|
||||
/* Potentially overloaded operator. */
|
||||
tmp |= MAY_BE_OBJECT | MAY_BE_RC1;
|
||||
}
|
||||
}
|
||||
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
|
||||
break;
|
||||
case ZEND_BEGIN_SILENCE:
|
||||
@ -2445,7 +2459,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
|
||||
}
|
||||
|
||||
tmp |= binary_op_result_type(
|
||||
ssa, get_compound_assign_op(opline->opcode), t1, t2, ssa_ops[i].op1_def);
|
||||
ssa, get_compound_assign_op(opline->opcode), t1, t2, ssa_ops[i].op1_def, optimization_level);
|
||||
if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) {
|
||||
tmp |= MAY_BE_RC1;
|
||||
}
|
||||
@ -3468,7 +3482,7 @@ static zend_class_entry *join_class_entries(
|
||||
return ce1;
|
||||
}
|
||||
|
||||
int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist)
|
||||
int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist, zend_long optimization_level)
|
||||
{
|
||||
zend_basic_block *blocks = ssa->cfg.blocks;
|
||||
zend_ssa_var *ssa_vars = ssa->vars;
|
||||
@ -3535,7 +3549,7 @@ int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script
|
||||
}
|
||||
} else if (ssa_vars[j].definition >= 0) {
|
||||
i = ssa_vars[j].definition;
|
||||
if (zend_update_type_info(op_array, ssa, script, worklist, i) == FAILURE) {
|
||||
if (zend_update_type_info(op_array, ssa, script, worklist, i, optimization_level) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
@ -3707,7 +3721,7 @@ static zend_bool can_convert_to_double(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int zend_type_narrowing(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa)
|
||||
static int zend_type_narrowing(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level)
|
||||
{
|
||||
uint32_t bitset_len = zend_bitset_len(ssa->vars_count);
|
||||
zend_bitset visited, worklist;
|
||||
@ -3751,7 +3765,7 @@ static int zend_type_narrowing(const zend_op_array *op_array, const zend_script
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (zend_infer_types_ex(op_array, script, ssa, worklist) != SUCCESS) {
|
||||
if (zend_infer_types_ex(op_array, script, ssa, worklist, optimization_level) != SUCCESS) {
|
||||
free_alloca(visited, use_heap);
|
||||
return FAILURE;
|
||||
}
|
||||
@ -4001,7 +4015,7 @@ void zend_func_return_info(const zend_op_array *op_array,
|
||||
ret->has_range = tmp_has_range;
|
||||
}
|
||||
|
||||
static int zend_infer_types(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa)
|
||||
static int zend_infer_types(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level)
|
||||
{
|
||||
zend_ssa_var_info *ssa_var_info = ssa->var_info;
|
||||
int ssa_vars_count = ssa->vars_count;
|
||||
@ -4018,13 +4032,13 @@ static int zend_infer_types(const zend_op_array *op_array, const zend_script *sc
|
||||
ssa_var_info[j].type = 0;
|
||||
}
|
||||
|
||||
if (zend_infer_types_ex(op_array, script, ssa, worklist) != SUCCESS) {
|
||||
if (zend_infer_types_ex(op_array, script, ssa, worklist, optimization_level) != SUCCESS) {
|
||||
free_alloca(worklist, use_heap);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Narrowing integer initialization to doubles */
|
||||
zend_type_narrowing(op_array, script, ssa);
|
||||
zend_type_narrowing(op_array, script, ssa, optimization_level);
|
||||
|
||||
if (ZEND_FUNC_INFO(op_array)) {
|
||||
zend_func_return_info(op_array, script, 1, 0, &ZEND_FUNC_INFO(op_array)->return_info);
|
||||
@ -4034,7 +4048,7 @@ static int zend_infer_types(const zend_op_array *op_array, const zend_script *sc
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa) /* {{{ */
|
||||
int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level) /* {{{ */
|
||||
{
|
||||
zend_ssa_var_info *ssa_var_info;
|
||||
int i;
|
||||
@ -4067,7 +4081,7 @@ int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (zend_infer_types(op_array, script, ssa) != SUCCESS) {
|
||||
if (zend_infer_types(op_array, script, ssa, optimization_level) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
@ -243,7 +243,7 @@ BEGIN_EXTERN_C()
|
||||
|
||||
int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa);
|
||||
int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa);
|
||||
int zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa);
|
||||
int zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level);
|
||||
|
||||
uint32_t zend_array_element_type(uint32_t t1, int write, int insert);
|
||||
|
||||
@ -253,7 +253,7 @@ int zend_inference_narrowing_meet(zend_ssa_var_info *var_info, zend_ssa_range *
|
||||
int zend_inference_widening_meet(zend_ssa_var_info *var_info, zend_ssa_range *r);
|
||||
void zend_inference_check_recursive_dependencies(zend_op_array *op_array);
|
||||
|
||||
int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist);
|
||||
int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist, zend_long optimization_level);
|
||||
|
||||
void zend_init_func_return_info(const zend_op_array *op_array,
|
||||
const zend_script *script,
|
||||
|
@ -39,12 +39,14 @@
|
||||
#define ZEND_OPTIMIZER_PASS_12 (1<<11) /* Adjust used stack */
|
||||
#define ZEND_OPTIMIZER_PASS_13 (1<<12) /* Remove unused variables */
|
||||
#define ZEND_OPTIMIZER_PASS_14 (1<<13) /* DCE (dead code elimination) */
|
||||
#define ZEND_OPTIMIZER_PASS_15 (1<<14) /* Collect constants */
|
||||
#define ZEND_OPTIMIZER_PASS_15 (1<<14) /* (unsafe) Collect constants */
|
||||
#define ZEND_OPTIMIZER_PASS_16 (1<<15) /* Inline functions */
|
||||
|
||||
#define ZEND_OPTIMIZER_IGNORE_OVERLOADING (1<<16) /* (unsafe) Ignore possibility of operator overloading */
|
||||
|
||||
#define ZEND_OPTIMIZER_ALL_PASSES 0x7FFFFFFF
|
||||
|
||||
#define DEFAULT_OPTIMIZATION_LEVEL "0x7FFFBFFF"
|
||||
#define DEFAULT_OPTIMIZATION_LEVEL "0x7FFEBFFF"
|
||||
|
||||
|
||||
#define ZEND_DUMP_AFTER_PASS_1 ZEND_OPTIMIZER_PASS_1
|
||||
|
Loading…
Reference in New Issue
Block a user