Browse Source

Use zend_regenerate_var_liveliness_info() to regenerate information after pass two.

pull/1392/head
Dmitry Stogov 11 years ago
parent
commit
7052e56979
  1. 3
      Zend/zend_compile.h
  2. 63
      Zend/zend_opcode.c
  3. 37
      ext/opcache/Optimizer/zend_optimizer.c

3
Zend/zend_compile.h

@ -732,7 +732,8 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...);
ZEND_API int open_file_for_scanning(zend_file_handle *file_handle);
ZEND_API void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size);
ZEND_API void destroy_op_array(zend_op_array *op_array);
ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array);
ZEND_API void zend_generate_var_liveliness_info(zend_op_array *op_array);
ZEND_API void zend_regenerate_var_liveliness_info(zend_op_array *op_array);
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle);
ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce);
ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce);

63
Zend/zend_opcode.c

@ -751,7 +751,7 @@ ZEND_API int pass_two(zend_op_array *op_array)
CG(context).literals_size = op_array->last_literal;
}
op_array->T_liveliness = generate_var_liveliness_info(op_array);
zend_generate_var_liveliness_info(op_array);
opline = op_array->opcodes;
end = opline + op_array->last;
@ -889,9 +889,9 @@ static zend_always_inline uint32_t liveliness_kill_var(zend_op_array *op_array,
return count;
}
ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_array *op_array, zend_bool done_pass_two)
{
uint32_t i, op_live_total = 0;
uint32_t i, op_live_total = 0, var;
void *checkpoint = zend_arena_checkpoint(CG(arena));
uint32_t *info, info_off = op_array->last + 1;
uint32_t *Tstart = zend_arena_alloc(&CG(arena), sizeof(uint32_t) * op_array->T);
@ -919,25 +919,42 @@ ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
&& cur_op->opcode != ZEND_DECLARE_INHERITED_CLASS_DELAYED
&& cur_op->opcode != ZEND_DECLARE_ANON_CLASS
&& cur_op->opcode != ZEND_DECLARE_ANON_INHERITED_CLASS) {
if (done_pass_two) {
var = EX_VAR_TO_NUM(cur_op->result.var) - op_array->last_var;
} else {
var = cur_op->result.var;
}
/* Objects created via ZEND_NEW are only fully initialized after the DO_FCALL (constructor call) */
if (cur_op->opcode == ZEND_NEW) {
Tstart[cur_op->result.var] = cur_op->op2.opline_num - 1;
Tstart[var] = cur_op->op2.opline_num - 1;
} else {
Tstart[cur_op->result.var] = cur_op - op_array->opcodes;
Tstart[var] = cur_op - op_array->opcodes;
}
}
if ((cur_op->op1_type & (IS_VAR | IS_TMP_VAR))
&& Tstart[cur_op->op1.var] != (uint32_t)-1
&& cur_op->opcode != ZEND_ROPE_ADD /* the following opcodes don't free TMP */
&& cur_op->opcode != ZEND_FETCH_LIST
&& cur_op->opcode != ZEND_CASE
&& cur_op->opcode != ZEND_FE_FETCH_R
&& cur_op->opcode != ZEND_FE_FETCH_RW) {
op_live_total += liveliness_kill_var(op_array, cur_op, cur_op->op1.var, Tstart, opTs);
if (cur_op->op1_type & (IS_VAR | IS_TMP_VAR)) {
if (done_pass_two) {
var = EX_VAR_TO_NUM(cur_op->op1.var) - op_array->last_var;
} else {
var = cur_op->op1.var;
}
if (Tstart[var] != (uint32_t)-1
&& cur_op->opcode != ZEND_ROPE_ADD /* the following opcodes don't free TMP */
&& cur_op->opcode != ZEND_FETCH_LIST
&& cur_op->opcode != ZEND_CASE
&& cur_op->opcode != ZEND_FE_FETCH_R
&& cur_op->opcode != ZEND_FE_FETCH_RW) {
op_live_total += liveliness_kill_var(op_array, cur_op, var, Tstart, opTs);
}
}
if (cur_op->op2_type & (IS_VAR | IS_TMP_VAR)
&& Tstart[cur_op->op2.var] != (uint32_t)-1) {
op_live_total += liveliness_kill_var(op_array, cur_op, cur_op->op2.var, Tstart, opTs);
if (cur_op->op2_type & (IS_VAR | IS_TMP_VAR)) {
if (done_pass_two) {
var = EX_VAR_TO_NUM(cur_op->op2.var) - op_array->last_var;
} else {
var = cur_op->op2.var;
}
if (Tstart[var] != (uint32_t)-1) {
op_live_total += liveliness_kill_var(op_array, cur_op, var, Tstart, opTs);
}
}
}
@ -965,10 +982,22 @@ ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
}
zend_arena_release(&CG(arena), checkpoint);
return info;
}
ZEND_API void zend_generate_var_liveliness_info(zend_op_array *op_array)
{
op_array->T_liveliness = generate_var_liveliness_info_ex(op_array, 0);
}
ZEND_API void zend_regenerate_var_liveliness_info(zend_op_array *op_array)
{
if (op_array->T_liveliness) {
efree(op_array->T_liveliness);
}
op_array->T_liveliness = generate_var_liveliness_info_ex(op_array, 1);
}
int print_class(zend_class_entry *class_entry)
{
printf("Class %s:\n", ZSTR_VAL(class_entry->name));

37
ext/opcache/Optimizer/zend_optimizer.c

@ -458,6 +458,17 @@ static void zend_optimize(zend_op_array *op_array,
if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
zend_optimizer_compact_literals(op_array, ctx);
}
if ((ZEND_OPTIMIZER_PASS_1
|ZEND_OPTIMIZER_PASS_2
|ZEND_OPTIMIZER_PASS_3
|ZEND_OPTIMIZER_PASS_4
|ZEND_OPTIMIZER_PASS_5
|ZEND_OPTIMIZER_PASS_9
|ZEND_OPTIMIZER_PASS_10
|ZEND_OPTIMIZER_PASS_11) & OPTIMIZATION_LEVEL) {
zend_regenerate_var_liveliness_info(op_array);
}
}
static void zend_accel_optimize(zend_op_array *op_array,
@ -465,8 +476,6 @@ static void zend_accel_optimize(zend_op_array *op_array,
{
zend_op *opline, *end;
efree(op_array->T_liveliness);
/* Revert pass_two() */
opline = op_array->opcodes;
end = opline + op_array->last;
@ -512,39 +521,15 @@ static void zend_accel_optimize(zend_op_array *op_array,
/* Do actual optimizations */
zend_optimize(op_array, ctx);
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
opline->op1.var = EX_VAR_TO_NUM(opline->op1.var) - op_array->last_var;
}
if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
opline->op2.var = EX_VAR_TO_NUM(opline->op2.var) - op_array->last_var;
}
if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
opline->result.var = EX_VAR_TO_NUM(opline->result.var) - op_array->last_var;
}
opline++;
}
op_array->T_liveliness = generate_var_liveliness_info(op_array);
/* Redo pass_two() */
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {
if (opline->op1_type == IS_CONST) {
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, opline->op1.var + op_array->last_var);
}
if (opline->op2_type == IS_CONST) {
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, opline->op2.var + op_array->last_var);
}
if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, opline->result.var + op_array->last_var);
}
switch (opline->opcode) {
case ZEND_JMP:

Loading…
Cancel
Save