Use zval_ptr_dtor_nogc() to free IS_TMP_VAR operands.

Removed ZEND_SWITCH_FREE opcode (ZEND_FREE used instead).
This commit is contained in:
Dmitry Stogov 2014-09-23 17:21:29 +04:00
parent b2795700cc
commit 06103d65b1
11 changed files with 462 additions and 538 deletions

View file

@ -859,7 +859,7 @@ static int generate_free_loop_var(znode *var TSRMLS_DC) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = var->op_type == IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE;
opline->opcode = ZEND_FREE;
SET_NODE(opline->op1, var);
SET_UNUSED(opline->op2);
}
@ -3588,7 +3588,7 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) /* {{{ */
zend_end_loop(get_next_op_number(CG(active_op_array)), 1 TSRMLS_CC);
if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) {
zend_emit_op(NULL, expr_node.op_type == IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE,
zend_emit_op(NULL, ZEND_FREE,
&expr_node, NULL TSRMLS_CC);
} else if (expr_node.op_type == IS_CONST) {
zval_dtor(&expr_node.u.constant);

View file

@ -100,15 +100,6 @@ static const zend_internal_function zend_pass_function = {
#define FREE_OP(should_free) \
if (should_free.var) { \
if ((zend_uintptr_t)should_free.var & 1L) { \
zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
} else { \
zval_ptr_dtor_nogc(should_free.var); \
} \
}
#define FREE_OP_IF_VAR(should_free) \
if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
zval_ptr_dtor_nogc(should_free.var); \
}
@ -117,10 +108,6 @@ static const zend_internal_function zend_pass_function = {
zval_ptr_dtor_nogc(should_free.var); \
}
#define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
#define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
/* End of zend_execute_locks.h */
#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
@ -362,7 +349,7 @@ static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_
break;
case IS_TMP_VAR:
ret = EX_VAR(node->var);
should_free->var = TMP_FREE(ret);
should_free->var = ret;
return ret;
break;
case IS_VAR:
@ -392,7 +379,7 @@ static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const
break;
case IS_TMP_VAR:
ret = EX_VAR(node->var);
should_free->var = TMP_FREE(ret);
should_free->var = ret;
return ret;
break;
case IS_VAR:
@ -744,10 +731,12 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
ZVAL_COPY(retval, value);
}
zval_ptr_dtor(value);
FREE_OP_IF_VAR(free_value);
if (value_type == IS_VAR) {
FREE_OP(free_value);
}
}
static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, int value_type, zval *result TSRMLS_DC)
static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result TSRMLS_DC)
{
zend_string *old_str;
@ -779,12 +768,6 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu
zend_string_release(tmp);
} else {
Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
if (value_type == IS_TMP_VAR) {
/* we can safely free final_value here
* because separation is done only
* in case value_type == IS_VAR */
zval_dtor(value);
}
}
/*
* the value of an assignment to a string offset is undefined
@ -824,7 +807,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
return variable_ptr;
}
garbage = Z_COUNTED_P(variable_ptr);
if (GC_REFCOUNT(garbage) == 1) {
if (--GC_REFCOUNT(garbage) == 0) {
ZVAL_COPY_VALUE(variable_ptr, value);
if (value_type == IS_CONST) {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
@ -836,10 +819,9 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
Z_ADDREF_P(variable_ptr);
}
}
_zval_dtor_func(garbage ZEND_FILE_LINE_CC);
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
return variable_ptr;
} else { /* we need to split */
GC_REFCOUNT(garbage)--;
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
if ((Z_COLLECTABLE_P(variable_ptr)) &&
UNEXPECTED(!GC_INFO(garbage))) {
@ -1036,7 +1018,7 @@ fetch_from_array:
zend_long offset;
if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
zval_dtor(container);
zval_ptr_dtor_nogc(container);
convert_to_array:
ZVAL_NEW_ARR(container);
zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
@ -1337,13 +1319,9 @@ static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_of
if (nest_levels>1) {
zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
if (brk_opline->opcode == ZEND_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_ptr_dtor(EX_VAR(brk_opline->op1.var));
}
} else if (brk_opline->opcode == ZEND_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_dtor(EX_VAR(brk_opline->op1.var));
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
}
}
}

View file

@ -57,19 +57,9 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
} else if (brk_cont->brk > op_num) {
zend_op *brk_opline = op_array->opcodes + brk_cont->brk;
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
{
if (brk_opline->opcode == ZEND_FREE) {
zval *var = EX_VAR_2(execute_data, brk_opline->op1.var);
zval_ptr_dtor(var);
}
break;
case ZEND_FREE:
{
zval *var = EX_VAR_2(execute_data, brk_opline->op1.var);
zval_dtor(var);
}
break;
zval_ptr_dtor_nogc(var);
}
}
}

View file

@ -1643,26 +1643,27 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
FREE_OP2();
value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
if (UNEXPECTED(variable_ptr != NULL)) {
zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
FREE_OP(free_op_data1);
} else {
variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (IS_TMP_FREE(free_op_data1)) {
zval_dtor(value);
}
FREE_OP(free_op_data1);
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
FREE_OP_VAR_PTR(free_op_data2);
} else {
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
if ((opline+1)->op1_type == IS_VAR) {
FREE_OP(free_op_data1);
}
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
FREE_OP_VAR_PTR(free_op_data2);
}
}
FREE_OP_IF_VAR(free_op_data1);
}
FREE_OP1_VAR_PTR();
/* assign_dim has two opcodes! */
@ -1684,7 +1685,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (OP2_TYPE == IS_TMP_VAR) {
zval_dtor(value);
FREE_OP2();
}
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
@ -2041,11 +2042,7 @@ ZEND_VM_HANDLER(70, ZEND_FREE, TMP|VAR, ANY)
USE_OPLINE
SAVE_OPLINE();
if (OP1_TYPE == IS_TMP_VAR) {
zval_dtor(EX_VAR(opline->op1.var));
} else {
zval_ptr_dtor(EX_VAR(opline->op1.var));
}
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@ -3652,13 +3649,9 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
brk_opline = EX(func)->op_array.opcodes + el->brk;
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
if (brk_opline->opcode == ZEND_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_ptr_dtor(EX_VAR(brk_opline->op1.var));
}
} else if (brk_opline->opcode == ZEND_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_dtor(EX_VAR(brk_opline->op1.var));
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
}
}
ZEND_VM_JMP(opline->op1.jmp_addr);
@ -3680,16 +3673,6 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(49, ZEND_SWITCH_FREE, VAR, ANY)
{
USE_OPLINE
SAVE_OPLINE();
zval_ptr_dtor(EX_VAR(opline->op1.var));
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
{
USE_OPLINE
@ -5485,13 +5468,9 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
if (brk_opline->opcode == ZEND_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_ptr_dtor(EX_VAR(brk_opline->op1.var));
}
} else if (brk_opline->opcode == ZEND_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_dtor(EX_VAR(brk_opline->op1.var));
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -245,7 +245,7 @@ $op2_get_obj_zval_ptr_ptr = array(
$op1_free_op = array(
"ANY" => "FREE_OP(free_op1)",
"TMP" => "zval_dtor(free_op1.var)",
"TMP" => "zval_ptr_dtor_nogc(free_op1.var)",
"VAR" => "zval_ptr_dtor_nogc(free_op1.var)",
"CONST" => "",
"UNUSED" => "",
@ -254,7 +254,7 @@ $op1_free_op = array(
$op2_free_op = array(
"ANY" => "FREE_OP(free_op2)",
"TMP" => "zval_dtor(free_op2.var)",
"TMP" => "zval_ptr_dtor_nogc(free_op2.var)",
"VAR" => "zval_ptr_dtor_nogc(free_op2.var)",
"CONST" => "",
"UNUSED" => "",
@ -262,7 +262,7 @@ $op2_free_op = array(
);
$op1_free_op_if_var = array(
"ANY" => "FREE_OP_IF_VAR(free_op1)",
"ANY" => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(free_op1.var);}",
"TMP" => "",
"VAR" => "zval_ptr_dtor_nogc(free_op1.var)",
"CONST" => "",
@ -271,7 +271,7 @@ $op1_free_op_if_var = array(
);
$op2_free_op_if_var = array(
"ANY" => "FREE_OP_IF_VAR(free_op2)",
"ANY" => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(free_op1.var);}",
"TMP" => "",
"VAR" => "zval_ptr_dtor_nogc(free_op2.var)",
"CONST" => "",

View file

@ -71,7 +71,7 @@ const char *zend_vm_opcodes_map[169] = {
"ZEND_JMPZ_EX",
"ZEND_JMPNZ_EX",
"ZEND_CASE",
"ZEND_SWITCH_FREE",
NULL,
"ZEND_BRK",
"ZEND_CONT",
"ZEND_BOOL",

View file

@ -72,7 +72,6 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
#define ZEND_JMPZ_EX 46
#define ZEND_JMPNZ_EX 47
#define ZEND_CASE 48
#define ZEND_SWITCH_FREE 49
#define ZEND_BRK 50
#define ZEND_CONT 51
#define ZEND_BOOL 52

View file

@ -203,14 +203,12 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
j = 0;
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_SWITCH_FREE)) {
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_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_SWITCH_FREE) {
op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE) {
parent = op_array->brk_cont_array[parent].parent;
}
op_array->brk_cont_array[i].parent = parent;
@ -224,8 +222,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
j = 0;
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_SWITCH_FREE)) {
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE) {
if (i != j) {
op_array->brk_cont_array[j] = op_array->brk_cont_array[i];
}
@ -1363,10 +1360,9 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
} else if (0&& block->op1_to != block &&
block->op1_to != blocks &&
op_array->last_try_catch == 0 &&
target->opcode != ZEND_FREE &&
target->opcode != ZEND_SWITCH_FREE) {
target->opcode != ZEND_FREE) {
/* Block Reordering (saves one JMP on each "for" loop iteration)
* It is disabled for some cases (ZEND_FREE/ZEND_SWITCH_FREE)
* It is disabled for some cases (ZEND_FREE)
* which may break register allocation.
*/
zend_bool can_reorder = 0;

View file

@ -205,8 +205,7 @@ void zend_optimizer_pass2(zend_op_array *op_array TSRMLS_DC)
array_offset = jmp_to->parent;
if (--nest_levels > 0) {
if (opline->opcode == ZEND_BRK &&
(op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE ||
op_array->opcodes[jmp_to->brk].opcode == ZEND_SWITCH_FREE)) {
op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE) {
dont_optimize = 1;
break;
}

View file

@ -232,7 +232,6 @@ const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */
CASE(ZEND_JMPZ_EX);
CASE(ZEND_JMPNZ_EX);
CASE(ZEND_CASE);
CASE(ZEND_SWITCH_FREE);
CASE(ZEND_BRK);
CASE(ZEND_CONT);
CASE(ZEND_BOOL);