static void zend_dump_type_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_type_constraint *constraint, uint32_t dump_flags)
{
fprintf(stderr, " TYPE");
- zend_dump_type_info(constraint->type_mask, NULL, 0, dump_flags);
+ zend_dump_type_info(constraint->type_mask, constraint->ce, 1, dump_flags);
}
static void zend_dump_range_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_range_constraint *r, uint32_t dump_flags)
if (ssa_vars[j].definition_phi) {
zend_ssa_phi *p = ssa_vars[j].definition_phi;
if (p->pi >= 0) {
+ zend_class_entry *ce = ssa_var_info[p->sources[0]].ce;
+ int is_instanceof = ssa_var_info[p->sources[0]].is_instanceof;
tmp = get_ssa_var_info(ssa, p->sources[0]);
+
if (!p->has_range_constraint) {
- tmp &= p->constraint.type.type_mask;
+ zend_ssa_type_constraint *constraint = &p->constraint.type;
+ tmp &= constraint->type_mask;
+ if ((tmp & MAY_BE_OBJECT) && constraint->ce && ce != constraint->ce) {
+ if (!ce) {
+ ce = constraint->ce;
+ is_instanceof = 1;
+ } else if (is_instanceof && instanceof_function(constraint->ce, ce)) {
+ ce = constraint->ce;
+ } else {
+ /* Ignore the constraint (either ce instanceof constraint->ce or
+ * they are unrelated, as far as we can statically determine) */
+ }
+ }
}
+
UPDATE_SSA_TYPE(tmp, j);
- if (ssa_var_info[p->sources[0]].ce) {
- UPDATE_SSA_OBJ_TYPE(ssa_var_info[p->sources[0]].ce, ssa_var_info[p->sources[0]].is_instanceof, j);
- }
+ UPDATE_SSA_OBJ_TYPE(ce, is_instanceof, j);
} else {
int first = 1;
int is_instanceof = 0;
static void pi_type_mask(zend_ssa_phi *phi, uint32_t type_mask) {
phi->has_range_constraint = 0;
+ phi->constraint.type.ce = NULL;
phi->constraint.type.type_mask = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN;
phi->constraint.type.type_mask |= type_mask;
if (type_mask & MAY_BE_NULL) {
* Order of Phis is importent, Pis must be placed before Phis
*/
static void place_essa_pis(
- zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa,
- zend_dfg *dfg) /* {{{ */ {
+ zend_arena **arena, const zend_script *script, const zend_op_array *op_array,
+ uint32_t build_flags, zend_ssa *ssa, zend_dfg *dfg) /* {{{ */ {
zend_basic_block *blocks = ssa->cfg.blocks;
int j, blocks_count = ssa->cfg.blocks_count;
for (j = 0; j < blocks_count; j++) {
pi_not_type_mask(pi, type_mask);
}
}
+ } else if (opline->op1_type == IS_TMP_VAR && (opline-1)->opcode == ZEND_INSTANCEOF &&
+ opline->op1.var == (opline-1)->result.var && (opline-1)->op1_type == IS_CV &&
+ (opline-1)->op2_type == IS_CONST) {
+ int var = EX_VAR_TO_NUM((opline-1)->op1.var);
+ zend_string *lcname = Z_STR_P(CRT_CONSTANT((opline-1)->op2) + 1);
+ zend_class_entry *ce = zend_hash_find_ptr(&script->class_table, lcname);
+ if (!ce) {
+ ce = zend_hash_find_ptr(CG(class_table), lcname);
+ if (!ce || ce->type != ZEND_INTERNAL_CLASS) {
+ continue;
+ }
+ }
+
+ if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
+ pi_type_mask(pi, MAY_BE_OBJECT);
+ pi->constraint.type.ce = ce;
+ }
}
}
}
}
/* }}} */
-int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, uint32_t *func_flags) /* {{{ */
+int zend_build_ssa(zend_arena **arena, const zend_script *script, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, uint32_t *func_flags) /* {{{ */
{
zend_basic_block *blocks = ssa->cfg.blocks;
zend_ssa_block *ssa_blocks;
/* Place e-SSA pis. This will add additional "def" points, so it must
* happen before def propagation. */
- place_essa_pis(arena, op_array, build_flags, ssa, &dfg);
+ place_essa_pis(arena, script, op_array, build_flags, ssa, &dfg);
/* SSA construction, Step 1: Propagate "def" sets in merge points */
do {
#ifndef ZEND_SSA_H
#define ZEND_SSA_H
+#include "zend_optimizer.h"
#include "zend_cfg.h"
typedef struct _zend_ssa_range {
} zend_ssa_range_constraint;
typedef struct _zend_ssa_type_constraint {
- uint32_t type_mask; /* If -1 this is a range constraint */
+ uint32_t type_mask; /* Type mask to intersect with */
+ zend_class_entry *ce; /* Class entry for instanceof constraints */
} zend_ssa_type_constraint;
typedef union _zend_ssa_pi_constraint {
BEGIN_EXTERN_C()
-int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, uint32_t *func_flags);
+int zend_build_ssa(zend_arena **arena, const zend_script *script, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, uint32_t *func_flags);
int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa);
int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var);