mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
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:
parent
b2795700cc
commit
06103d65b1
11 changed files with 462 additions and 538 deletions
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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" => "",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue