mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
ZEND_FETCH_*_R operations simplified and can't be used with EXT_TYPE_UNUSED flag any more. Thit is very rare and useless case. ZEND_FREE might be required after them instead.
This commit is contained in:
parent
8aad91d14a
commit
ca4de03eed
3
NEWS
3
NEWS
@ -22,6 +22,9 @@ PHP NEWS
|
||||
. $GLOBALS became a JIT autoglobal, so it's initialized only if used
|
||||
(this may affect opcode caches)
|
||||
. simplified string ofset reading. $str[1][0] now is a legal construct.
|
||||
. ZEND_FETCH_*_R operations simplified and can't be used with EXT_TYPE_UNUSED
|
||||
flag any more. Thit is very rare and useless case. ZEND_FREE might be
|
||||
required after them instead.
|
||||
- Added concept of interned strings. All strings constants known at compile
|
||||
time are allocated in a single copy and never changed. (Dmitry)
|
||||
- Added an optimization which saves memory and emalloc/efree calls for empty
|
||||
|
@ -63,10 +63,18 @@ print "\nDone\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
|
||||
Notice: Uninitialized string offset: %i in %s on line 6
|
||||
|
||||
Notice: Uninitialized string offset: 0 in %s on line 10
|
||||
|
||||
Notice: Uninitialized string offset: 0 in %s on line 12
|
||||
|
||||
Notice: Uninitialized string offset: %i in %s on line 14
|
||||
|
||||
Notice: Uninitialized string offset: %i in %s on line 16
|
||||
|
||||
Notice: Uninitialized string offset: 0 in %s on line 18
|
||||
|
||||
Notice: Uninitialized string offset: 4 in %s on line 28
|
||||
|
||||
Notice: Uninitialized string offset: 4 in %s on line 34
|
||||
@ -77,6 +85,8 @@ Notice: Uninitialized string offset: 4 in %s on line 42
|
||||
|
||||
Notice: Uninitialized string offset: 4 in %s on line 46
|
||||
|
||||
Notice: Uninitialized string offset: 12 in %s on line 50
|
||||
|
||||
Notice: Uninitialized string offset: 12 in %s on line 52
|
||||
b
|
||||
Done
|
||||
|
29
Zend/tests/result_unused.phpt
Normal file
29
Zend/tests/result_unused.phpt
Normal file
@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Unused result of fetch operations
|
||||
--FILE--
|
||||
<?php
|
||||
$x = array(1);
|
||||
$a = "x";
|
||||
$$a;
|
||||
|
||||
$x = array(array(2));
|
||||
$x[0];
|
||||
|
||||
$x = "str";
|
||||
$x[0];
|
||||
$x[3];
|
||||
|
||||
class Foo {
|
||||
public $prop = array(3);
|
||||
function __get($name) {
|
||||
return array(4);
|
||||
}
|
||||
}
|
||||
$x = new Foo();
|
||||
$x->prop;
|
||||
$x->y;
|
||||
echo "ok\n";
|
||||
--EXPECTF--
|
||||
Notice: Uninitialized string offset: 3 in %sresult_unused.php on line 11
|
||||
ok
|
||||
|
@ -1422,7 +1422,19 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
if (opline->result_type == IS_VAR
|
||||
&& opline->result.var == op1->u.op.var) {
|
||||
opline->result_type |= EXT_TYPE_UNUSED;
|
||||
if (opline->opcode == ZEND_FETCH_R ||
|
||||
opline->opcode == ZEND_FETCH_DIM_R ||
|
||||
opline->opcode == ZEND_FETCH_OBJ_R) {
|
||||
/* It's very rare and useless case. It's better to use
|
||||
additional FREE opcode and simplify the FETCH handlers
|
||||
their selves */
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_FREE;
|
||||
SET_NODE(opline->op1, op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
} else {
|
||||
opline->result_type |= EXT_TYPE_UNUSED;
|
||||
}
|
||||
} else {
|
||||
while (opline>CG(active_op_array)->opcodes) {
|
||||
if (opline->opcode == ZEND_FETCH_DIM_R
|
||||
@ -6065,7 +6077,7 @@ int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, ze
|
||||
{
|
||||
zend_auto_global auto_global;
|
||||
|
||||
auto_global.name = zend_new_interned_string(name, name_len + 1, 0 TSRMLS_CC);
|
||||
auto_global.name = zend_new_interned_string((char*)name, name_len + 1, 0 TSRMLS_CC);
|
||||
auto_global.name_len = name_len;
|
||||
auto_global.auto_global_callback = auto_global_callback;
|
||||
auto_global.jit = jit;
|
||||
|
@ -1218,23 +1218,18 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont
|
||||
|
||||
case IS_ARRAY:
|
||||
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
|
||||
if (result) {
|
||||
AI_SET_PTR(result, *retval);
|
||||
PZVAL_LOCK(*retval);
|
||||
}
|
||||
AI_SET_PTR(result, *retval);
|
||||
PZVAL_LOCK(*retval);
|
||||
return;
|
||||
break;
|
||||
|
||||
case IS_NULL:
|
||||
if (result) {
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
}
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
return;
|
||||
break;
|
||||
|
||||
case IS_STRING: {
|
||||
zval tmp;
|
||||
zval *ptr;
|
||||
|
||||
if (Z_TYPE_P(dim) != IS_LONG) {
|
||||
switch(Z_TYPE_P(dim)) {
|
||||
@ -1255,25 +1250,22 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont
|
||||
convert_to_long(&tmp);
|
||||
dim = &tmp;
|
||||
}
|
||||
if (result) {
|
||||
zval *ptr;
|
||||
|
||||
ALLOC_ZVAL(ptr);
|
||||
INIT_PZVAL(ptr);
|
||||
Z_TYPE_P(ptr) = IS_STRING;
|
||||
ALLOC_ZVAL(ptr);
|
||||
INIT_PZVAL(ptr);
|
||||
Z_TYPE_P(ptr) = IS_STRING;
|
||||
|
||||
if (Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) {
|
||||
zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
|
||||
Z_STRVAL_P(ptr) = STR_EMPTY_ALLOC();
|
||||
Z_STRLEN_P(ptr) = 0;
|
||||
} else {
|
||||
Z_STRVAL_P(ptr) = (char*)emalloc(2);
|
||||
Z_STRVAL_P(ptr)[0] = Z_STRVAL_P(container)[Z_LVAL_P(dim)];
|
||||
Z_STRVAL_P(ptr)[1] = 0;
|
||||
Z_STRLEN_P(ptr) = 1;
|
||||
}
|
||||
AI_SET_PTR(result, ptr);
|
||||
if (Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) {
|
||||
zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
|
||||
Z_STRVAL_P(ptr) = STR_EMPTY_ALLOC();
|
||||
Z_STRLEN_P(ptr) = 0;
|
||||
} else {
|
||||
Z_STRVAL_P(ptr) = (char*)emalloc(2);
|
||||
Z_STRVAL_P(ptr)[0] = Z_STRVAL_P(container)[Z_LVAL_P(dim)];
|
||||
Z_STRVAL_P(ptr)[1] = 0;
|
||||
Z_STRLEN_P(ptr) = 1;
|
||||
}
|
||||
AI_SET_PTR(result, ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -1292,14 +1284,8 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont
|
||||
overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
|
||||
|
||||
if (overloaded_result) {
|
||||
if (result) {
|
||||
AI_SET_PTR(result, overloaded_result);
|
||||
PZVAL_LOCK(overloaded_result);
|
||||
} else if (Z_REFCOUNT_P(overloaded_result) == 0) {
|
||||
/* Destroy unused result from offsetGet() magic method */
|
||||
Z_SET_REFCOUNT_P(overloaded_result, 1);
|
||||
zval_ptr_dtor(&overloaded_result);
|
||||
}
|
||||
AI_SET_PTR(result, overloaded_result);
|
||||
PZVAL_LOCK(overloaded_result);
|
||||
} else if (result) {
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
@ -1309,15 +1295,11 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont
|
||||
}
|
||||
}
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (result) {
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
}
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1105,31 +1105,29 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
|
||||
if (OP1_TYPE != IS_CONST && varname == &tmp_varname) {
|
||||
zval_dtor(&tmp_varname);
|
||||
}
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
|
||||
}
|
||||
PZVAL_LOCK(*retval);
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
case BP_VAR_IS:
|
||||
AI_SET_PTR(&EX_T(opline->result.var), *retval);
|
||||
break;
|
||||
case BP_VAR_UNSET: {
|
||||
zend_free_op free_res;
|
||||
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
|
||||
}
|
||||
PZVAL_LOCK(*retval);
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
case BP_VAR_IS:
|
||||
AI_SET_PTR(&EX_T(opline->result.var), *retval);
|
||||
break;
|
||||
case BP_VAR_UNSET: {
|
||||
zend_free_op free_res;
|
||||
|
||||
PZVAL_UNLOCK(*retval, &free_res);
|
||||
if (retval != &EG(uninitialized_zval_ptr)) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(retval);
|
||||
}
|
||||
PZVAL_LOCK(*retval);
|
||||
FREE_OP_VAR_PTR(free_res);
|
||||
PZVAL_UNLOCK(*retval, &free_res);
|
||||
if (retval != &EG(uninitialized_zval_ptr)) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(retval);
|
||||
}
|
||||
/* break missing intentionally */
|
||||
default:
|
||||
EX_T(opline->result.var).var.ptr_ptr = retval;
|
||||
break;
|
||||
PZVAL_LOCK(*retval);
|
||||
FREE_OP_VAR_PTR(free_res);
|
||||
}
|
||||
/* break missing intentionally */
|
||||
default:
|
||||
EX_T(opline->result.var).var.ptr_ptr = retval;
|
||||
break;
|
||||
}
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
@ -1182,7 +1180,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VAR|CV, CONST|TMP|VAR|CV)
|
||||
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
|
||||
}
|
||||
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
|
||||
zend_fetch_dimension_address_read(!RETURN_VALUE_USED(opline)?NULL:&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
|
||||
zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
|
||||
FREE_OP2();
|
||||
FREE_OP1_VAR_PTR();
|
||||
CHECK_EXCEPTION();
|
||||
@ -1345,10 +1343,8 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP
|
||||
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
|
||||
UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
||||
zend_error(E_NOTICE, "Trying to get property of non-object");
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
|
||||
}
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
|
||||
FREE_OP2();
|
||||
} else {
|
||||
zval *retval;
|
||||
@ -1360,16 +1356,8 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP
|
||||
/* here we are sure we are dealing with an object */
|
||||
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
|
||||
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
if (Z_REFCOUNT_P(retval) == 0) {
|
||||
GC_REMOVE_ZVAL_FROM_BUFFER(retval);
|
||||
zval_dtor(retval);
|
||||
FREE_ZVAL(retval);
|
||||
}
|
||||
} else {
|
||||
PZVAL_LOCK(retval);
|
||||
AI_SET_PTR(&EX_T(opline->result.var), retval);
|
||||
}
|
||||
PZVAL_LOCK(retval);
|
||||
AI_SET_PTR(&EX_T(opline->result.var), retval);
|
||||
|
||||
if (IS_OP2_TMP_FREE()) {
|
||||
zval_ptr_dtor(&offset);
|
||||
@ -1480,10 +1468,8 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
|
||||
|
||||
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
|
||||
UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
|
||||
}
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
|
||||
FREE_OP2();
|
||||
} else {
|
||||
zval *retval;
|
||||
@ -1495,16 +1481,8 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
|
||||
/* here we are sure we are dealing with an object */
|
||||
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
|
||||
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
if (Z_REFCOUNT_P(retval) == 0) {
|
||||
GC_REMOVE_ZVAL_FROM_BUFFER(retval);
|
||||
zval_dtor(retval);
|
||||
FREE_ZVAL(retval);
|
||||
}
|
||||
} else {
|
||||
PZVAL_LOCK(retval);
|
||||
AI_SET_PTR(&EX_T(opline->result.var), retval);
|
||||
}
|
||||
PZVAL_LOCK(retval);
|
||||
AI_SET_PTR(&EX_T(opline->result.var), retval);
|
||||
|
||||
if (IS_OP2_TMP_FREE()) {
|
||||
zval_ptr_dtor(&offset);
|
||||
@ -1608,10 +1586,8 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_DIM_TMP_VAR, CONST|TMP, CONST)
|
||||
container = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
|
||||
if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
|
||||
}
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
|
||||
} else {
|
||||
zend_free_op free_op2;
|
||||
zval *value = *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
|
||||
@ -2008,12 +1984,16 @@ ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMP|VAR|CV, ANY)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(70, ZEND_FREE, TMP, ANY)
|
||||
ZEND_VM_HANDLER(70, ZEND_FREE, TMP|VAR, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
SAVE_OPLINE();
|
||||
zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
|
||||
if (OP1_TYPE == IS_TMP_VAR) {
|
||||
zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
|
||||
} else {
|
||||
zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
|
||||
}
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user