mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'temporary_cleaning' of https://github.com/dstogov/php-src into temporary_cleaning
This commit is contained in:
commit
1dbb007e4a
10 changed files with 296 additions and 47 deletions
|
@ -6276,10 +6276,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;
|
||||
|
||||
begin_opline_num = get_next_op_number(CG(active_op_array));
|
||||
zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
|
||||
|
||||
if (expr_ast->kind == ZEND_AST_VAR) {
|
||||
|
@ -6290,15 +6288,7 @@ 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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -6626,10 +6616,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;
|
||||
|
|
|
@ -328,6 +328,9 @@ typedef struct _zend_internal_function_info {
|
|||
zend_bool _is_variadic;
|
||||
} zend_internal_function_info;
|
||||
|
||||
#define ZEND_LIVE_ROPE (1 << 0)
|
||||
#define ZEND_LIVE_SILENCE (1 << 1)
|
||||
|
||||
struct _zend_op_array {
|
||||
/* Common elements */
|
||||
zend_uchar type;
|
||||
|
@ -351,6 +354,7 @@ struct _zend_op_array {
|
|||
int last_var;
|
||||
uint32_t T;
|
||||
zend_string **vars;
|
||||
uint32_t *T_liveliness;
|
||||
|
||||
int last_brk_cont;
|
||||
int last_try_catch;
|
||||
|
@ -727,6 +731,7 @@ 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_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);
|
||||
|
|
|
@ -2385,6 +2385,41 @@ static zend_always_inline zend_generator *zend_get_running_generator(zend_execut
|
|||
static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
|
||||
{
|
||||
int i;
|
||||
|
||||
if (EX(func)->op_array.T_liveliness && op_num < EX(func)->op_array.last) {
|
||||
uint32_t *off = EX(func)->op_array.T_liveliness + EX(func)->op_array.T_liveliness[op_num];
|
||||
uint32_t *until = EX(func)->op_array.T_liveliness + EX(func)->op_array.T_liveliness[op_num + 1];
|
||||
while (off < until) {
|
||||
uint32_t var = *(off++);
|
||||
|
||||
if (var & ZEND_LIVE_ROPE) {
|
||||
/* free incomplete rope */
|
||||
zend_string **rope = (zend_string **) EX_VAR(var & ~ZEND_LIVE_ROPE);
|
||||
zend_op *last = EX(func)->op_array.opcodes + op_num;
|
||||
while (last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT) {
|
||||
ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
|
||||
last--;
|
||||
}
|
||||
if (last->opcode == ZEND_ROPE_INIT) {
|
||||
zend_string_release(*rope);
|
||||
} else {
|
||||
int j = last->extended_value;
|
||||
do {
|
||||
zend_string_release(rope[j]);
|
||||
} while (j--);
|
||||
}
|
||||
} else if (var & ZEND_LIVE_SILENCE) {
|
||||
/* restore previous error_reporting value */
|
||||
var = var & ~ZEND_LIVE_SILENCE;
|
||||
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(var)) != 0) {
|
||||
EG(error_reporting) = Z_LVAL_P(EX_VAR(var));
|
||||
}
|
||||
} else {
|
||||
zval_ptr_dtor_nogc(EX_VAR(var));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UNEXPECTED(EX(call))) {
|
||||
zend_execute_data *call = EX(call);
|
||||
zend_op *opline = EX(func)->op_array.opcodes + op_num;
|
||||
|
@ -2511,34 +2546,13 @@ static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data
|
|||
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) {
|
||||
/* ZEND_FREE opcodes are handled by temporary variable freeing */
|
||||
if (brk_opline->opcode == ZEND_FE_FREE) {
|
||||
zval *var = EX_VAR(brk_opline->op1.var);
|
||||
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);
|
||||
zend_op *last = EX(func)->op_array.opcodes + op_num;
|
||||
while (last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT) {
|
||||
ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
|
||||
last--;
|
||||
}
|
||||
if (last->opcode == ZEND_ROPE_INIT) {
|
||||
zend_string_release(*rope);
|
||||
} else {
|
||||
int j = last->extended_value;
|
||||
do {
|
||||
zend_string_release(rope[j]);
|
||||
} while (j--);
|
||||
}
|
||||
} else if (brk_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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
|
|||
op_array->vars = NULL;
|
||||
|
||||
op_array->T = 0;
|
||||
op_array->T_liveliness = NULL;
|
||||
|
||||
op_array->function_name = NULL;
|
||||
op_array->filename = zend_get_compiled_filename();
|
||||
|
@ -389,6 +390,9 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
|
|||
if (op_array->try_catch_array) {
|
||||
efree(op_array->try_catch_array);
|
||||
}
|
||||
if (op_array->T_liveliness) {
|
||||
efree(op_array->T_liveliness);
|
||||
}
|
||||
if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
|
||||
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
|
||||
}
|
||||
|
@ -576,7 +580,7 @@ static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num,
|
|||
fast_call_var = op_array->opcodes[op_array->try_catch_array[i].finally_end].op1.var;
|
||||
|
||||
/* generate a FAST_CALL to finally block */
|
||||
start_op = get_next_op_number(op_array);
|
||||
start_op = get_next_op_number(op_array);
|
||||
|
||||
opline = get_next_op(op_array);
|
||||
opline->opcode = ZEND_FAST_CALL;
|
||||
|
@ -751,6 +755,9 @@ ZEND_API int pass_two(zend_op_array *op_array)
|
|||
op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
|
||||
CG(context).literals_size = op_array->last_literal;
|
||||
}
|
||||
|
||||
op_array->T_liveliness = generate_var_liveliness_info(op_array);
|
||||
|
||||
opline = op_array->opcodes;
|
||||
end = opline + op_array->last;
|
||||
while (opline < end) {
|
||||
|
@ -840,6 +847,174 @@ int pass_two_wrapper(zval *el)
|
|||
return pass_two((zend_op_array *) Z_PTR_P(el));
|
||||
}
|
||||
|
||||
typedef struct _var_live_info {
|
||||
struct _var_live_info *next;
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
} var_live_info;
|
||||
|
||||
typedef struct _op_var_info {
|
||||
struct _op_var_info *next;
|
||||
uint32_t var;
|
||||
} op_var_info;
|
||||
|
||||
ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
|
||||
{
|
||||
void *checkpoint = zend_arena_checkpoint(CG(arena));
|
||||
var_live_info **TsTop = zend_arena_alloc(&CG(arena), sizeof(var_live_info *) * op_array->T);
|
||||
var_live_info **Ts = zend_arena_alloc(&CG(arena), sizeof(var_live_info *) * op_array->T);
|
||||
int i, op_live_total = 0;
|
||||
uint32_t *info, info_off = op_array->last + 1;
|
||||
op_var_info *opTsTop = zend_arena_alloc(&CG(arena), sizeof(op_var_info) * (op_array->last + 1));
|
||||
op_var_info **opTs = zend_arena_alloc(&CG(arena), sizeof(op_var_info *) * (op_array->last + 1));
|
||||
|
||||
for (i = 0; i < op_array->T; i++) {
|
||||
TsTop[i] = Ts[i] = zend_arena_alloc(&CG(arena), sizeof(var_live_info));
|
||||
Ts[i]->next = NULL;
|
||||
Ts[i]->start = Ts[i]->end = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i <= op_array->last; i++) {
|
||||
opTs[i] = &opTsTop[i];
|
||||
opTs[i]->var = -1;
|
||||
opTs[i]->next = NULL;
|
||||
}
|
||||
|
||||
zend_op *end_op = op_array->opcodes + op_array->last;
|
||||
zend_op *cur_op = op_array->opcodes;
|
||||
for (; cur_op < end_op; cur_op++) {
|
||||
if ((cur_op->result_type & (IS_VAR | IS_TMP_VAR))
|
||||
&& !(cur_op->result_type & EXT_TYPE_UNUSED)
|
||||
&& cur_op->opcode != ZEND_BOOL /* why ??? */
|
||||
&& cur_op->opcode != ZEND_JMPZ_EX /* why ??? */
|
||||
&& cur_op->opcode != ZEND_JMPNZ_EX /* why ??? */
|
||||
&& (cur_op->opcode != ZEND_QM_ASSIGN
|
||||
|| (cur_op + 1)->opcode != ZEND_JMP) /* why ??? */
|
||||
&& cur_op->opcode != ZEND_CASE /* ??? exception for opcache, is anyway bool */
|
||||
&& cur_op->opcode != ZEND_FE_RESET_R /* FOREACH TMP is handled using brk_cont_array */
|
||||
&& cur_op->opcode != ZEND_FE_RESET_RW /* FOREACH TMP is handled using brk_cont_array */
|
||||
&& cur_op->opcode != ZEND_ROPE_ADD /* the following opocodes reuse TMP created before */
|
||||
&& cur_op->opcode != ZEND_ADD_ARRAY_ELEMENT
|
||||
&& cur_op->opcode != ZEND_FAST_CALL /* passes fast_call */
|
||||
&& cur_op->opcode != ZEND_FETCH_CLASS /* the following opcodes pass class_entry */
|
||||
&& cur_op->opcode != ZEND_DECLARE_CLASS
|
||||
&& cur_op->opcode != ZEND_DECLARE_INHERITED_CLASS
|
||||
&& cur_op->opcode != ZEND_DECLARE_INHERITED_CLASS_DELAYED
|
||||
&& cur_op->opcode != ZEND_DECLARE_ANON_CLASS
|
||||
&& cur_op->opcode != ZEND_DECLARE_ANON_INHERITED_CLASS) {
|
||||
var_live_info *T = Ts[cur_op->result.var];
|
||||
if (~T->end) {
|
||||
T = Ts[cur_op->result.var] = T->next = zend_arena_alloc(&CG(arena), sizeof(var_live_info));
|
||||
T->next = NULL;
|
||||
T->start = T->end = -1;
|
||||
}
|
||||
if (!~T->start) {
|
||||
/* Objects created via ZEND_NEW are only fully initialized after the DO_FCALL (constructor call) */
|
||||
if (cur_op->opcode == ZEND_NEW) {
|
||||
T->start = cur_op->op2.opline_num - 1;
|
||||
} else {
|
||||
T->start = cur_op - op_array->opcodes;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((cur_op->op1_type & (IS_VAR | IS_TMP_VAR))
|
||||
&& cur_op->opcode != ZEND_FE_FETCH_R /* FOREACH TMP is handled using brk_cont_array */
|
||||
&& cur_op->opcode != ZEND_FE_FETCH_RW /* FOREACH TMP is handled using brk_cont_array */
|
||||
&& cur_op->opcode != ZEND_FE_FREE /* FOREACH TMP is handled using brk_cont_array */
|
||||
&& cur_op->opcode != ZEND_ROPE_ADD /* the following opcodes don't free TMP */
|
||||
&& cur_op->opcode != ZEND_CASE
|
||||
&& cur_op->opcode != ZEND_FETCH_LIST
|
||||
&& cur_op->opcode != ZEND_FAST_RET /* uses fast_call */
|
||||
&& cur_op->opcode != ZEND_NEW /* the following opcodes use class_entry */
|
||||
&& cur_op->opcode != ZEND_INIT_STATIC_METHOD_CALL
|
||||
&& cur_op->opcode != ZEND_FETCH_CONSTANT
|
||||
&& cur_op->opcode != ZEND_ADD_INTERFACE
|
||||
&& cur_op->opcode != ZEND_ADD_TRAIT
|
||||
&& cur_op->opcode != ZEND_BIND_TRAITS
|
||||
&& cur_op->opcode != ZEND_VERIFY_ABSTRACT_CLASS) {
|
||||
var_live_info *T = Ts[cur_op->op1.var];
|
||||
if (~T->start) {
|
||||
T->end = cur_op - op_array->opcodes;
|
||||
if (cur_op->opcode == ZEND_OP_DATA) {
|
||||
T->end--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((cur_op->op2_type & (IS_VAR | IS_TMP_VAR))
|
||||
&& cur_op->opcode != ZEND_FETCH_R /* the following opcodes use class_entry */
|
||||
&& cur_op->opcode != ZEND_FETCH_W
|
||||
&& cur_op->opcode != ZEND_FETCH_RW
|
||||
&& cur_op->opcode != ZEND_FETCH_IS
|
||||
&& cur_op->opcode != ZEND_FETCH_FUNC_ARG
|
||||
&& cur_op->opcode != ZEND_FETCH_UNSET
|
||||
&& cur_op->opcode != ZEND_UNSET_VAR
|
||||
&& cur_op->opcode != ZEND_ISSET_ISEMPTY_VAR
|
||||
&& cur_op->opcode != ZEND_INSTANCEOF) {
|
||||
var_live_info *T = Ts[cur_op->op2.var];
|
||||
if (~T->start) {
|
||||
T->end = cur_op - op_array->opcodes;
|
||||
if (cur_op->opcode == ZEND_OP_DATA) {
|
||||
T->end--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < op_array->T; i++) {
|
||||
int j;
|
||||
var_live_info *T = TsTop[i];
|
||||
|
||||
do {
|
||||
if (!~T->start) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ZEND_ASSERT(~T->end);
|
||||
|
||||
for (j = T->start + 1; j < T->end; j++) {
|
||||
if (op_array->opcodes[j].opcode != ZEND_THROW) {
|
||||
op_var_info *opT = opTs[j];
|
||||
if (~opT->var) {
|
||||
opT = opTs[j] = opT->next = zend_arena_alloc(&CG(arena), sizeof(op_var_info));
|
||||
opT->next = NULL;
|
||||
}
|
||||
opT->var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + i);;
|
||||
if (op_array->opcodes[T->end].opcode == ZEND_ROPE_END) {
|
||||
opT->var |= ZEND_LIVE_ROPE;
|
||||
} else if (op_array->opcodes[T->end].opcode == ZEND_END_SILENCE) {
|
||||
opT->var |= ZEND_LIVE_SILENCE;
|
||||
}
|
||||
op_live_total++;
|
||||
}
|
||||
}
|
||||
} while ((T = T->next));
|
||||
}
|
||||
|
||||
if (!op_live_total) {
|
||||
zend_arena_release(&CG(arena), checkpoint);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info = emalloc(op_live_total * sizeof(uint32_t) + (op_array->last + 1) * sizeof(uint32_t));
|
||||
|
||||
for (i = 0; i < op_array->last; i++) {
|
||||
op_var_info *opT = &opTsTop[i];
|
||||
info[i] = info_off;
|
||||
if (!~opT->var) {
|
||||
opT = NULL;
|
||||
}
|
||||
while (opT) {
|
||||
info[info_off++] = opT->var;
|
||||
opT = opT->next;
|
||||
}
|
||||
}
|
||||
info[i] = info_off;
|
||||
|
||||
zend_arena_release(&CG(arena), checkpoint);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
int print_class(zend_class_entry *class_entry)
|
||||
{
|
||||
printf("Class %s:\n", ZSTR_VAL(class_entry->name));
|
||||
|
|
|
@ -207,17 +207,13 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
|
|||
for (i = 0; i< op_array->last_brk_cont; i++) {
|
||||
if (op_array->brk_cont_array[i].start >= 0 &&
|
||||
(op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE)) {
|
||||
int parent = op_array->brk_cont_array[i].parent;
|
||||
|
||||
while (parent >= 0 &&
|
||||
op_array->brk_cont_array[parent].start < 0 &&
|
||||
(op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FE_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode != ZEND_ROPE_END ||
|
||||
op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_END_SILENCE)) {
|
||||
op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FE_FREE)) {
|
||||
parent = op_array->brk_cont_array[parent].parent;
|
||||
}
|
||||
op_array->brk_cont_array[i].parent = parent;
|
||||
|
@ -232,9 +228,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
|
|||
for (i = 0; i< op_array->last_brk_cont; i++) {
|
||||
if (op_array->brk_cont_array[i].start >= 0 &&
|
||||
(op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE)) {
|
||||
if (i != j) {
|
||||
op_array->brk_cont_array[j] = op_array->brk_cont_array[i];
|
||||
}
|
||||
|
|
|
@ -482,6 +482,8 @@ 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;
|
||||
|
@ -527,15 +529,39 @@ 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:
|
||||
|
|
|
@ -464,6 +464,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
|
|||
SERIALIZE_STR(op_array->doc_comment);
|
||||
SERIALIZE_PTR(op_array->try_catch_array);
|
||||
SERIALIZE_PTR(op_array->prototype);
|
||||
SERIALIZE_PTR(op_array->T_liveliness);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -987,6 +988,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
|
|||
UNSERIALIZE_STR(op_array->doc_comment);
|
||||
UNSERIALIZE_PTR(op_array->try_catch_array);
|
||||
UNSERIALIZE_PTR(op_array->prototype);
|
||||
UNSERIALIZE_PTR(op_array->T_liveliness);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -618,6 +618,10 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
|||
zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
|
||||
}
|
||||
|
||||
if (op_array->T_liveliness) {
|
||||
zend_accel_store(op_array->T_liveliness, sizeof(uint32_t) * op_array->T_liveliness[op_array->last]);
|
||||
}
|
||||
|
||||
if (op_array->vars) {
|
||||
if (already_stored) {
|
||||
persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
|
||||
|
|
|
@ -241,6 +241,10 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
|
|||
ADD_DUP_SIZE(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
|
||||
}
|
||||
|
||||
if (op_array->T_liveliness) {
|
||||
ADD_DUP_SIZE(op_array->T_liveliness, sizeof(uint32_t) * op_array->T_liveliness[op_array->last]);
|
||||
}
|
||||
|
||||
if (op_array->vars) {
|
||||
int i;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "phpdbg_opcode.h"
|
||||
#include "phpdbg_utils.h"
|
||||
#include "ext/standard/php_string.h"
|
||||
#include "zend_smart_str.h"
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
|
||||
|
||||
|
@ -124,6 +125,44 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars) /*{
|
|||
break;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (ops->T_liveliness) {
|
||||
uint32_t *var = ops->T_liveliness + ops->T_liveliness[op - ops->opcodes];
|
||||
uint32_t *end = ops->T_liveliness + ops->T_liveliness[op - ops->opcodes + 1];
|
||||
|
||||
if (var != end) {
|
||||
smart_str str = {0};
|
||||
|
||||
smart_str_appends(&str, "; [@");
|
||||
smart_str_append_long(&str, EX_VAR_TO_NUM(((*var) & ~0x3)) - ops->last_var);
|
||||
while (++var != end) {
|
||||
smart_str_appends(&str, ", @");
|
||||
smart_str_append_long(&str, EX_VAR_TO_NUM(((*var) & ~0x3)) - ops->last_var);
|
||||
}
|
||||
smart_str_appendc(&str, ']');
|
||||
smart_str_0(&str);
|
||||
|
||||
asprintf(&decode[0],
|
||||
"%-20s %-20s %-20s%-20s",
|
||||
decode[1] ? decode[1] : "",
|
||||
decode[2] ? decode[2] : "",
|
||||
decode[3] ? decode[3] : "",
|
||||
ZSTR_VAL(str.s));
|
||||
|
||||
smart_str_free(&str);
|
||||
|
||||
if (decode[1])
|
||||
free(decode[1]);
|
||||
if (decode[2])
|
||||
free(decode[2]);
|
||||
if (decode[3])
|
||||
free(decode[3]);
|
||||
|
||||
return decode[0];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
asprintf(&decode[0],
|
||||
"%-20s %-20s %-20s",
|
||||
decode[1] ? decode[1] : "",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue