Skip to content

Commit

Permalink
We don't nees zend_op_array->brk_cont_array at run-time anymore.
Browse files Browse the repository at this point in the history
Move zend_op_array->brk_cont_array into CG(context).brk_cont_array.
Use more compact zend_op_array->live_range instead of zend_op_array->brk_cont_array.
Semantic is kept unchanged.
  • Loading branch information
dstogov committed Nov 10, 2015
1 parent 71092b7 commit baf97b1
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 148 deletions.
15 changes: 15 additions & 0 deletions Zend/tests/temporary_cleaning_008.phpt
@@ -0,0 +1,15 @@
--TEST--
Optimization of constant switch expression
--FILE--
<?php
try {
switch ("1" . (int)2) {
case 12:
throw new Exception();
}
} catch (Exception $e) {
echo "exception\n";
}
?>
--EXPECT--
exception
64 changes: 43 additions & 21 deletions Zend/zend_compile.c
Expand Up @@ -218,16 +218,22 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
CG(context).vars_size = 0;
CG(context).literals_size = 0;
CG(context).current_brk_cont = -1;
CG(context).backpatch_count = 0;
CG(context).in_finally = 0;
CG(context).fast_call_var = -1;
CG(context).current_brk_cont = -1;
CG(context).last_brk_cont = 0;
CG(context).brk_cont_array = NULL;
CG(context).labels = NULL;
}
/* }}} */

void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
{
if (CG(context).brk_cont_array) {
efree(CG(context).brk_cont_array);
CG(context).brk_cont_array = NULL;
}
if (CG(context).labels) {
zend_hash_destroy(CG(context).labels);
FREE_HASHTABLE(CG(context).labels);
Expand Down Expand Up @@ -567,14 +573,28 @@ void zend_stop_lexing(void)
LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
}

static void zend_add_live_range(zend_op_array *op_array, uint32_t start, uint32_t end) /* {{{ */
{
zend_live_range *range;

if (start != end) {
op_array->last_live_range++;
op_array->live_range = erealloc(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
range = op_array->live_range + op_array->last_live_range - 1;
range->start = start;
range->end = end;
}
}
/* }}} */

static inline void zend_begin_loop(zend_uchar free_opcode, const znode *loop_var) /* {{{ */
{
zend_brk_cont_element *brk_cont_element;
int parent = CG(context).current_brk_cont;
zend_loop_var info = {0};

CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
CG(context).current_brk_cont = CG(context).last_brk_cont;
brk_cont_element = get_next_brk_cont_element();
brk_cont_element->parent = parent;

if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
Expand All @@ -597,7 +617,7 @@ static inline void zend_begin_loop(zend_uchar free_opcode, const znode *loop_var
static inline void zend_end_loop(int cont_addr) /* {{{ */
{
zend_brk_cont_element *brk_cont_element
= &CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont];
= &CG(context).brk_cont_array[CG(context).current_brk_cont];
brk_cont_element->cont = cont_addr;
brk_cont_element->brk = get_next_op_number(CG(active_op_array));
CG(context).current_brk_cont = brk_cont_element->parent;
Expand Down Expand Up @@ -3734,14 +3754,14 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
ZVAL_NULL(label);

current = opline->extended_value;
for (; current != dest->brk_cont; current = op_array->brk_cont_array[current].parent) {
for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
if (current == -1) {
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
CG(zend_lineno) = opline->lineno;
zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
}
if (op_array->brk_cont_array[current].start >= 0) {
if (CG(context).brk_cont_array[current].start >= 0) {
remove_oplines--;
}
}
Expand Down Expand Up @@ -3989,7 +4009,9 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */

zend_end_loop(opnum_fetch);

zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
zend_add_live_range(CG(active_op_array),
opnum_fetch, opline - CG(active_op_array)->opcodes);
}
/* }}} */

Expand Down Expand Up @@ -4046,10 +4068,11 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
znode expr_node, case_node;
zend_op *opline;
uint32_t *jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
uint32_t opnum_default_jmp;
uint32_t opnum_default_jmp, opnum_start;

zend_compile_expr(&expr_node, expr_ast);

opnum_start = get_next_op_number(CG(active_op_array));
zend_begin_loop(ZEND_FREE, &expr_node);

case_node.op_type = IS_TMP_VAR;
Expand Down Expand Up @@ -4112,7 +4135,9 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
zend_end_loop(get_next_op_number(CG(active_op_array)));

if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) {
zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
zend_add_live_range(CG(active_op_array),
opnum_start, opline - CG(active_op_array)->opcodes);
} else if (expr_node.op_type == IS_CONST) {
zval_dtor(&expr_node.u.constant);
}
Expand Down Expand Up @@ -6426,8 +6451,8 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
znode silence_node;
uint32_t begin_opline_num, end_opline_num;
zend_brk_cont_element *brk_cont_element;
uint32_t begin_opline_num;
zend_op *opline;

begin_opline_num = get_next_op_number(CG(active_op_array));
zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
Expand All @@ -6440,15 +6465,12 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
zend_compile_expr(result, expr_ast);
}

end_opline_num = get_next_op_number(CG(active_op_array));
zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
opline = zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);

/* Store BEGIN_SILENCE/END_SILENCE pair to restore previous
* EG(error_reporting) value on exception */
brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
brk_cont_element->start = begin_opline_num;
brk_cont_element->cont = brk_cont_element->brk = end_opline_num;
brk_cont_element->parent = -1;
zend_add_live_range(CG(active_op_array),
begin_opline_num + 1, opline - CG(active_op_array)->opcodes);
}
/* }}} */

Expand Down Expand Up @@ -6768,10 +6790,6 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
GET_NODE(result, opline->result);
} else {
uint32_t var;
zend_brk_cont_element *info = get_next_brk_cont_element(CG(active_op_array));
info->start = rope_init_lineno;
info->parent = CG(context).current_brk_cont;
info->cont = info->brk = opline - CG(active_op_array)->opcodes;

init_opline->extended_value = j;
opline->opcode = ZEND_ROPE_END;
Expand All @@ -6785,6 +6803,10 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
get_temporary_variable(CG(active_op_array));
i--;
}

zend_add_live_range(CG(active_op_array),
rope_init_lineno, opline - CG(active_op_array)->opcodes);

/* Update all the previous opcodes to use the same variable */
while (opline != init_opline) {
opline--;
Expand Down
37 changes: 22 additions & 15 deletions Zend/zend_compile.h
Expand Up @@ -111,18 +111,6 @@ typedef struct _zend_declarables {
zend_long ticks;
} zend_declarables;

/* Compilation context that is different for each op array. */
typedef struct _zend_oparray_context {
uint32_t opcodes_size;
int vars_size;
int literals_size;
int current_brk_cont;
int backpatch_count;
int in_finally;
uint32_t fast_call_var;
HashTable *labels;
} zend_oparray_context;

/* Compilation context that is different for each file, but shared between op arrays. */
typedef struct _zend_file_context {
zend_declarables declarables;
Expand Down Expand Up @@ -185,6 +173,25 @@ typedef struct _zend_try_catch_element {
uint32_t finally_end;
} zend_try_catch_element;

typedef struct _zend_live_range {
uint32_t start;
uint32_t end;
} zend_live_range;

/* Compilation context that is different for each op array. */
typedef struct _zend_oparray_context {
uint32_t opcodes_size;
int vars_size;
int literals_size;
int backpatch_count;
int in_finally;
uint32_t fast_call_var;
int current_brk_cont;
int last_brk_cont;
zend_brk_cont_element *brk_cont_array;
HashTable *labels;
} zend_oparray_context;

/* method flags (types) */
#define ZEND_ACC_STATIC 0x01
#define ZEND_ACC_ABSTRACT 0x02
Expand Down Expand Up @@ -354,9 +361,9 @@ struct _zend_op_array {
uint32_t T;
zend_string **vars;

int last_brk_cont;
int last_live_range;
int last_try_catch;
zend_brk_cont_element *brk_cont_array;
zend_live_range *live_range;
zend_try_catch_element *try_catch_array;

/* static variables support */
Expand Down Expand Up @@ -755,7 +762,7 @@ zend_op *get_next_op(zend_op_array *op_array);
void init_op(zend_op *op);
int get_next_op_number(zend_op_array *op_array);
ZEND_API int pass_two(zend_op_array *op_array);
zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array);
zend_brk_cont_element *get_next_brk_cont_element(void);
ZEND_API zend_bool zend_is_compiling(void);
ZEND_API char *zend_make_compiled_string_description(const char *name);
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers);
Expand Down
41 changes: 22 additions & 19 deletions Zend/zend_execute.c
Expand Up @@ -2549,30 +2549,33 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num,
{
int i;

for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
const zend_brk_cont_element *brk_cont = &EX(func)->op_array.brk_cont_array[i];
if (brk_cont->start < 0) {
continue;
} else if (brk_cont->start > op_num) {
i = EX(func)->op_array.last_live_range;
while (i) {
const zend_live_range *range;

i--;
range = &EX(func)->op_array.live_range[i];
if (range->end <= op_num) {
/* further blocks will not be relevant... */
break;
} else if (op_num < brk_cont->brk) {
if (!catch_op_num || catch_op_num >= brk_cont->brk) {
zend_op *brk_opline = &EX(func)->op_array.opcodes[brk_cont->brk];

if (brk_opline->opcode == ZEND_FREE) {
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
} else if (brk_opline->opcode == ZEND_FE_FREE) {
zval *var = EX_VAR(brk_opline->op1.var);
} else if (op_num >= range->start) {
if (!catch_op_num || catch_op_num >= range->end) {
zend_op *opline = &EX(func)->op_array.opcodes[range->end];
uint32_t var_num = opline->op1.var;
zval *var = EX_VAR(var_num);

if (opline->opcode == ZEND_FREE) {
zval_ptr_dtor_nogc(var);
} else if (opline->opcode == ZEND_FE_FREE) {
if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
zend_hash_iterator_del(Z_FE_ITER_P(var));
}
zval_ptr_dtor_nogc(var);
} else if (brk_opline->opcode == ZEND_ROPE_END) {
zend_string **rope = (zend_string **) EX_VAR(brk_opline->op1.var);
} else if (opline->opcode == ZEND_ROPE_END) {
zend_string **rope = (zend_string **)var;
zend_op *last = EX(func)->op_array.opcodes + op_num;
while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
|| last->result.var != brk_opline->op1.var) {
|| last->result.var != var_num) {
ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
last--;
}
Expand All @@ -2584,10 +2587,10 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num,
zend_string_release(rope[j]);
} while (j--);
}
} else if (brk_opline->opcode == ZEND_END_SILENCE) {
} else if (opline->opcode == ZEND_END_SILENCE) {
/* restore previous error_reporting value */
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
if (!EG(error_reporting) && Z_LVAL_P(var) != 0) {
EG(error_reporting) = Z_LVAL_P(var);
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions Zend/zend_opcode.c
Expand Up @@ -78,9 +78,9 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->scope = NULL;
op_array->prototype = NULL;

op_array->brk_cont_array = NULL;
op_array->live_range = NULL;
op_array->try_catch_array = NULL;
op_array->last_brk_cont = 0;
op_array->last_live_range = 0;

op_array->static_variables = NULL;
op_array->last_try_catch = 0;
Expand Down Expand Up @@ -387,8 +387,8 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
if (op_array->doc_comment) {
zend_string_release(op_array->doc_comment);
}
if (op_array->brk_cont_array) {
efree(op_array->brk_cont_array);
if (op_array->live_range) {
efree(op_array->live_range);
}
if (op_array->try_catch_array) {
efree(op_array->try_catch_array);
Expand Down Expand Up @@ -451,11 +451,11 @@ int get_next_op_number(zend_op_array *op_array)
return op_array->last;
}

zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array)
zend_brk_cont_element *get_next_brk_cont_element(void)
{
op_array->last_brk_cont++;
op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont);
return &op_array->brk_cont_array[op_array->last_brk_cont-1];
CG(context).last_brk_cont++;
CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
}

static void zend_update_extended_info(zend_op_array *op_array)
Expand Down Expand Up @@ -570,7 +570,7 @@ static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const ze
int array_offset = opline->op1.num;
zend_brk_cont_element *jmp_to;
do {
jmp_to = &op_array->brk_cont_array[array_offset];
jmp_to = &CG(context).brk_cont_array[array_offset];
if (nest_levels > 1) {
array_offset = jmp_to->parent;
}
Expand Down

0 comments on commit baf97b1

Please sign in to comment.