Browse Source

Fixed destruction of VM handler operands (FREE_OP1 and family)

pull/678/head
Dmitry Stogov 12 years ago
parent
commit
1be0df935f
  1. 2
      Zend/zend.h
  2. 66
      Zend/zend_execute.c
  3. 329
      Zend/zend_vm_def.h
  4. 3221
      Zend/zend_vm_execute.h
  5. 46
      Zend/zend_vm_gen.php

2
Zend/zend.h

@ -356,11 +356,13 @@ static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc)
static zend_always_inline zend_uint zval_addref_p(zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
//??? if (Z_TYPE_P(pz) == IS_STRING && IS_INTERNED(Z_STR_P(pz))) return 1;
return ++Z_COUNTED_P(pz)->refcount;
}
static zend_always_inline zend_uint zval_delref_p(zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
//??? if (Z_TYPE_P(pz) == IS_STRING && IS_INTERNED(Z_STR_P(pz))) return 1;
return --Z_COUNTED_P(pz)->refcount;
}

66
Zend/zend_execute.c

@ -66,7 +66,7 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze
static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref TSRMLS_DC)
{
should_free->var = 0;
should_free->var = NULL;
if (Z_REFCOUNTED_P(z)) {
if (!Z_DELREF_P(z)) {
Z_SET_REFCOUNT_P(z, 1);
@ -184,7 +184,10 @@ ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute
static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
{
return should_free->var = EX_VAR(var);
zval *ret = EX_VAR(var);
should_free->var = ret;
return ret;
}
static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
@ -504,25 +507,27 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execu
static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
{
/* should_free->is_var = 0; */
zval *ret;
switch (op_type) {
case IS_CONST:
should_free->var = 0;
should_free->var = NULL;
return node->zv;
break;
case IS_TMP_VAR:
should_free->var = TMP_FREE(EX_VAR(node->var));
return EX_VAR(node->var);
ret = EX_VAR(node->var);
should_free->var = TMP_FREE(ret);
return ret;
break;
case IS_VAR:
return _get_zval_ptr_var(node->var, execute_data, should_free TSRMLS_CC);
break;
case IS_UNUSED:
should_free->var = 0;
should_free->var = NULL;
return NULL;
break;
case IS_CV:
should_free->var = 0;
should_free->var = NULL;
return _get_zval_ptr_cv(node->var, type TSRMLS_CC);
break;
EMPTY_SWITCH_DEFAULT_CASE()
@ -532,25 +537,27 @@ static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_
static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
{
/* should_free->is_var = 0; */
zval *ret;
switch (op_type) {
case IS_CONST:
should_free->var = 0;
should_free->var = NULL;
return node->zv;
break;
case IS_TMP_VAR:
should_free->var = TMP_FREE(EX_VAR(node->var));
return EX_VAR(node->var);
ret = EX_VAR(node->var);
should_free->var = TMP_FREE(ret);
return ret;
break;
case IS_VAR:
return _get_zval_ptr_var_deref(node->var, execute_data, should_free TSRMLS_CC);
break;
case IS_UNUSED:
should_free->var = 0;
should_free->var = NULL;
return NULL;
break;
case IS_CV:
should_free->var = 0;
should_free->var = NULL;
return _get_zval_ptr_cv_deref(node->var, type TSRMLS_CC);
break;
EMPTY_SWITCH_DEFAULT_CASE()
@ -558,21 +565,22 @@ static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const
return NULL;
}
//???
#if 0
static zend_always_inline zval **_get_zval_ptr_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
static zend_always_inline zval *_get_zval_ptr_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
{
zval** ptr_ptr = EX_T(var).var.ptr_ptr;
zval *ret = EX_VAR(var);
if (EXPECTED(ptr_ptr != NULL)) {
PZVAL_UNLOCK(*ptr_ptr, should_free);
} else {
/* string offset */
PZVAL_UNLOCK(EX_T(var).str_offset.str, should_free);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
ret = Z_INDIRECT_P(ret);
} else if (!Z_REFCOUNTED_P(ret)) {
should_free->var = ret;
return ret;
}
return ptr_ptr;
PZVAL_UNLOCK(ret, should_free);
return ret;
}
//???
#if 0
static zend_always_inline zval *_get_zval_ptr_var_fast(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
{
zval* ptr = EX_VAR(var);
@ -601,7 +609,7 @@ static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_exec
{
if (op_type == IS_UNUSED) {
if (EXPECTED(Z_TYPE(EG(This)) != IS_UNDEF)) {
should_free->var = 0;
should_free->var = NULL;
return &EG(This);
} else {
zend_error_noreturn(E_ERROR, "Using $this when not in object context");
@ -798,8 +806,10 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
if (value_type == IS_TMP_VAR) {
if (UNEXPECTED(Z_ISREF_P(value))) {
ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value));
value = &tmp;
} else {
ZVAL_COPY_VALUE(&tmp, value);
}
value = &tmp;
} else if (value_type == IS_CONST) {
if (UNEXPECTED(Z_ISREF_P(value))) {
value = Z_REFVAL_P(value);
@ -1286,7 +1296,7 @@ convert_to_array:
result = &EG(error_zval);
}
//??? if (dim_type == IS_TMP_VAR) {
//??? zval_ptr_dtor(&dim);
//??? zval_ptr_dtor(dim);
//??? }
}
return;
@ -1396,7 +1406,7 @@ static void zend_fetch_dimension_address_read(zval *result, zval *container, zva
}
}
//??? if (dim_type == IS_TMP_VAR) {
//??? zval_ptr_dtor(&dim);
//??? zval_ptr_dtor(dim);
//??? }
}
return;

329
Zend/zend_vm_def.h

@ -331,7 +331,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
{
USE_OPLINE
zend_free_op free_op1, free_op2, free_op_data1;
zval *object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_RW);
zval *object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
@ -352,9 +352,9 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
}
} else {
/* here we are sure we are dealing with an object */
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property);
//??? }
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
@ -414,11 +414,11 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
}
}
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property);
//??? } else {
FREE_OP2();
}
//??? }
FREE_OP(free_op_data1);
}
@ -442,7 +442,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, binary_op);
break;
case ZEND_ASSIGN_DIM: {
zval *container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_RW);
zval *container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
@ -456,13 +456,13 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
zend_fetch_dimension_address(EX_VAR((opline+1)->op2.var), container, dim, OP2_TYPE, BP_VAR_RW TSRMLS_CC);
value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
var_ptr = _get_zval_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
}
break;
default:
value = GET_OP2_ZVAL_PTR(BP_VAR_R);
var_ptr = GET_OP1_ZVAL_PTR(BP_VAR_RW);
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
/* do nothing */
break;
}
@ -510,9 +510,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
if (var_ptr != free_op_data2.var) {
FREE_OP_VAR_PTR(free_op_data2);
}
FREE_OP1_VAR_PTR();
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
@ -588,7 +586,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
int have_get_ptr = 0;
SAVE_OPLINE();
object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_RW);
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
retval = EX_VAR(opline->result.var);
@ -611,9 +609,9 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
/* here we are sure we are dealing with an object */
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property);
//??? }
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
@ -658,11 +656,11 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
}
}
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property);
//??? } else {
FREE_OP2();
}
//??? }
FREE_OP1_VAR_PTR();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@ -688,7 +686,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
int have_get_ptr = 0;
SAVE_OPLINE();
object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_RW);
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
retval = EX_VAR(opline->result.var);
@ -709,9 +707,9 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
/* here we are sure we are dealing with an object */
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property);
//??? }
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
@ -754,11 +752,11 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
}
}
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property);
//??? } else {
FREE_OP2();
}
//??? }
FREE_OP1_VAR_PTR();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@ -781,7 +779,7 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
zval *var_ptr;
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR(BP_VAR_RW);
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
@ -830,7 +828,7 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY)
zval *var_ptr;
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR(BP_VAR_RW);
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
@ -879,7 +877,7 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
zval *var_ptr, *retval;
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR(BP_VAR_RW);
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
@ -926,7 +924,7 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
zval *var_ptr, *retval;
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR(BP_VAR_RW);
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
@ -1058,9 +1056,8 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
//???
//ZVAL_NULL(retval);
ZVAL_NULL(EX_VAR(opline->result.var));
retval = EX_VAR(opline->result.var);
ZVAL_NULL(retval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
@ -1084,7 +1081,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (OP1_TYPE == IS_VAR && !free_op1.var) {
if (OP1_TYPE == IS_VAR && !OP1_FREE) {
Z_ADDREF_P(EX_VAR(opline->op1.var));
}
break;
@ -1119,7 +1116,6 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
}
/* break missing intentionally */
default:
//??? if (Z_REFCOUNTED_P(retval)) Z_ADDREF_P(retval);
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
break;
}
@ -1183,29 +1179,20 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
USE_OPLINE
zend_free_op free_op1, free_op2;
zval *container;
//???
int do_free = 1;
SAVE_OPLINE();
container = GET_OP1_ZVAL_PTR(BP_VAR_W);
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
//??? we must not free implicitly created array (it should be fixed in another way)
if (OP1_TYPE == IS_VAR && !Z_REFCOUNTED_P(container)) {
do_free = 0;
}
zend_fetch_dimension_address(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_W TSRMLS_CC);
FREE_OP2();
//??? if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
//??? EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
//??? }
//???
if (OP1_TYPE == IS_VAR && do_free) {
FREE_OP1_VAR_PTR();
}
/* We are going to assign the result by reference */
if (UNEXPECTED(opline->extended_value != 0)) {
@ -1218,10 +1205,10 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
if (Z_REFCOUNTED_P(retval_ptr)) {
Z_DELREF_P(retval_ptr);
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
Z_ADDREF_P(retval_ptr);
} else {
ZVAL_NEW_REF(retval_ptr, retval_ptr);
}
Z_ADDREF_P(retval_ptr);
}
}
@ -1275,7 +1262,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
container = GET_OP1_ZVAL_PTR(BP_VAR_W);
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
@ -1305,7 +1292,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV)
zval *container;
SAVE_OPLINE();
container = GET_OP1_ZVAL_PTR(BP_VAR_UNSET);
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_CV) {
SEPARATE_ZVAL_IF_NOT_REF(container);
@ -1362,9 +1349,9 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP
} else {
zval *retval;
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(offset);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(offset);
//??? }
/* 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), EX_VAR(opline->result.var) TSRMLS_CC);
@ -1373,11 +1360,11 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP
ZVAL_COPY(EX_VAR(opline->result.var), retval);
}
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(offset);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(offset);
//??? } else {
FREE_OP2();
}
//??? }
}
FREE_OP1();
@ -1400,20 +1387,21 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
SAVE_OPLINE();
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_W);
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property);
//??? }
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property);
//??? } else {
FREE_OP2();
}
//??? }
//??? if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
//??? EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
//??? }
@ -1430,10 +1418,10 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
if (Z_REFCOUNTED_P(retval_ptr)) {
Z_DELREF_P(retval_ptr);
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
Z_ADDREF_P(retval_ptr);
} else {
ZVAL_NEW_REF(retval_ptr, retval_ptr);
}
Z_ADDREF_P(retval_ptr);
}
}
@ -1450,20 +1438,21 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
SAVE_OPLINE();
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_RW);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property);
//??? }
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property);
//??? } else {
FREE_OP2();
}
//??? }
//??? if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
//??? EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
//??? }
@ -1491,9 +1480,9 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
} else {
zval *retval;
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(offset);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(offset);
//??? }
/* 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), EX_VAR(opline->result.var) TSRMLS_CC);
@ -1502,11 +1491,11 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZVAL_COPY(EX_VAR(opline->result.var), retval);
}
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(offset);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(offset);
//??? } else {
FREE_OP2();
}
//??? }
}
FREE_OP1();
@ -1526,20 +1515,21 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
SAVE_OPLINE();
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_W);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property);
//??? }
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property);
//??? } else {
FREE_OP2();
}
//??? }
//??? if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
//??? EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
//??? }
@ -1558,24 +1548,25 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zval *container, *property, *retval_ptr;
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_UNSET);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE == IS_CV) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property);
//??? }
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property);
//??? } else {
FREE_OP2();
}
//??? }
//??? if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
//??? EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
//??? }
@ -1623,22 +1614,22 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zval *property_name;
SAVE_OPLINE();
object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_W);
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property_name);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property_name);
//??? }
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property_name);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property_name);
//??? } else {
FREE_OP2();
}
//??? FREE_OP1_VAR_PTR();
//??? }
FREE_OP1_VAR_PTR();
/* assign_obj has two opcodes! */
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
@ -1652,7 +1643,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
zval *object_ptr;
SAVE_OPLINE();
object_ptr = GET_OP1_ZVAL_PTR(BP_VAR_W);
object_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
@ -1661,15 +1652,15 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
zend_free_op free_op2;
zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property_name);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(property_name);
//??? }
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(property_name);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(property_name);
//??? } else {
FREE_OP2();
}
//??? }
} else {
zend_free_op free_op2, free_op_data1, free_op_data2;
zval *value;
@ -1680,7 +1671,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
FREE_OP2();
value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
variable_ptr = _get_zval_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
if (RETURN_VALUE_USED(opline)) {
@ -1699,7 +1690,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
//??? FREE_OP_VAR_PTR(free_op_data2);
FREE_OP_VAR_PTR(free_op_data2);
} else {
if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
@ -1711,7 +1702,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
//??? FREE_OP_VAR_PTR(free_op_data2);
FREE_OP_VAR_PTR(free_op_data2);
}
FREE_OP_IF_VAR(free_op_data1);
}
@ -1731,7 +1722,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
SAVE_OPLINE();
value = GET_OP2_ZVAL_PTR(BP_VAR_R);
variable_ptr = GET_OP1_ZVAL_PTR(BP_VAR_W);
variable_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, OP2_TYPE TSRMLS_CC)) {
@ -1780,14 +1771,14 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
zval *value_ptr;
SAVE_OPLINE();
value_ptr = GET_OP2_ZVAL_PTR(BP_VAR_W);
value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W);
if (OP2_TYPE == IS_VAR &&
value_ptr &&
!Z_ISREF_P(value_ptr) &&
opline->extended_value == ZEND_RETURNS_FUNCTION /*???&&
!EX_T(opline->op2.var).var.fcall_returned_reference*/) {
if (free_op2.var == NULL) {
if (!OP2_FREE) {
PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */
}
zend_error(E_STRICT, "Only variables should be assigned by reference");
@ -1803,16 +1794,11 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
//??? zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
//??? }
variable_ptr = GET_OP1_ZVAL_PTR(BP_VAR_W);
variable_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if ((OP2_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) ||
(OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
//???: instead of FREE_OP2_VAR_PTR
if (OP2_TYPE == IS_VAR && free_op2.var) {
if (Z_REFCOUNTED_P(free_op2.var)) Z_DELREF_P(free_op2.var);
free_op2.var = NULL;
}
zend_assign_to_variable_reference(variable_ptr, value_ptr TSRMLS_CC);
if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
@ -1823,7 +1809,7 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
}
//??? FREE_OP1_VAR_PTR();
FREE_OP1_VAR_PTR();
FREE_OP2_VAR_PTR();
CHECK_EXCEPTION();
@ -2604,11 +2590,11 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
{
USE_OPLINE
zval *function_name, *func;
zval *function_name_ptr, *function_name, *func;
call_slot *call = EX(call_slots) + opline->result.num;
if (OP2_TYPE == IS_CONST) {
function_name = (zval*)(opline->op2.literal+1);
function_name_ptr = function_name = (zval*)(opline->op2.literal+1);
if (CACHED_PTR(opline->op2.literal->cache_slot)) {
call->fbc = CACHED_PTR(opline->op2.literal->cache_slot);
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
@ -2632,7 +2618,10 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
zend_free_op free_op2;
SAVE_OPLINE();
function_name = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
function_name_ptr = function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(function_name) == IS_REFERENCE) {
function_name = Z_REFVAL_P(function_name);
}
if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
@ -2667,7 +2656,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
if (OP2_TYPE == IS_VAR && OP2_FREE && Z_REFCOUNT_P(function_name) == 1 &&
call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
call->fbc->common.prototype = (zend_function*)function_name;
call->fbc->common.prototype = (zend_function*)function_name_ptr;
} else {
FREE_OP2();
}
@ -2882,7 +2871,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
break;
}
retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_W);
retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
@ -2893,10 +2882,13 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
//??? EX_T(opline->op1.var).var.fcall_returned_reference) {
//??? } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
zend_error(E_NOTICE, "Only variable references should be returned by reference");
//??? if (EX(return_value)) {
if (EX(return_value)) {
//??? ZVAL_DUP(EX(return_value), retval_ptr);
//??? }
//??? break;
zval tmp;
ZVAL_DUP(&tmp, retval_ptr);
ZVAL_NEW_REF(EX(return_value), &tmp);
}
break;
//??? }
}
@ -3120,7 +3112,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
zval *varptr;
SAVE_OPLINE();
varptr = GET_OP1_ZVAL_PTR(BP_VAR_W);
varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(varptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
@ -3705,7 +3697,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
SAVE_OPLINE();
if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && opline->extended_value) {
expr_ptr = GET_OP1_ZVAL_PTR(BP_VAR_W);
expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
@ -4058,7 +4050,7 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ulong hval;
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_UNSET);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_CV) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
@ -4120,15 +4112,19 @@ ZEND_VM_C_LABEL(num_index_dim):
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(offset);
}
//??? if (IS_OP2_TMP_FREE()) {
//???? if (OP2_TYPE == IS_CONST) {
//???? ZVAL_DUP(offset, offset);
//???? } else if (OP2_TYPE == IS_TMP_VAR) {
//??? MAKE_REAL_ZVAL_PTR(offset);
//??? }
Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(offset);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//???? if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_TMP_VAR) {
//??? zval_ptr_dtor(offset);
//??? } else {
FREE_OP2();
}
//??? }
break;
case IS_STRING:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
@ -4154,7 +4150,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zval *offset;
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_UNSET);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE != IS_VAR || container) {
@ -4162,19 +4158,19 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
SEPARATE_ZVAL_IF_NOT_REF(container);
}
if (Z_TYPE_P(container) == IS_OBJECT) {
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(offset);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(offset);
//??? }
if (Z_OBJ_HT_P(container)->unset_property) {
Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(offset);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(offset);
//??? } else {
FREE_OP2();
}
//??? }
} else {
FREE_OP2();
}
@ -4202,7 +4198,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
(opline->extended_value & ZEND_FE_RESET_VARIABLE)) {
array_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
array_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
if (Z_ISREF_P(array_ptr)) {
array_ref = array_ptr;
array_ptr = Z_REFVAL_P(array_ptr);
@ -4648,9 +4644,9 @@ ZEND_VM_C_LABEL(num_index_prop):
}
FREE_OP2();
} else if (Z_TYPE_P(container) == IS_OBJECT) {
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(offset);
}
//??? if (IS_OP2_TMP_FREE()) {
//??? MAKE_REAL_ZVAL_PTR(offset);
//??? }
if (prop_dim) {
if (Z_OBJ_HT_P(container)->has_property) {
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
@ -4666,11 +4662,11 @@ ZEND_VM_C_LABEL(num_index_prop):
result = 0;
}
}
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(offset);
} else {
//??? if (IS_OP2_TMP_FREE()) {
//??? zval_ptr_dtor(offset);
//??? } else {
FREE_OP2();
}
//??? }
} else if (Z_TYPE_P(container) == IS_STRING && !prop_dim) { /* string offsets */
zval tmp;
@ -5333,11 +5329,12 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
SAVE_OPLINE();
var_ptr = EX_VAR(opline->op1.var);
if (Z_TYPE_P(var_ptr) != IS_OBJECT && !Z_ISREF_P(var_ptr)) {
if (Z_REFCOUNTED_P(var_ptr) &&
if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
!Z_ISREF_P(var_ptr) &&
Z_REFCOUNTED_P(var_ptr) &&
Z_REFCOUNT_P(var_ptr) > 1) {
Z_DELREF_P(var_ptr);
}
ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr);
}
ZEND_VM_NEXT_OPCODE();
@ -5381,7 +5378,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
zval_copy_ctor(&generator->value);
}
} else {
zval *value_ptr = GET_OP1_ZVAL_PTR(BP_VAR_W);
zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");

3221
Zend/zend_vm_execute.h
File diff suppressed because it is too large
View File

46
Zend/zend_vm_gen.php

@ -135,6 +135,24 @@ $op2_get_zval_ptr = array(
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)",
);
$op1_get_zval_ptr_ptr = array(
"ANY" => "get_zval_ptr_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "NULL",
"VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "NULL",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)",
);
$op2_get_zval_ptr_ptr = array(
"ANY" => "get_zval_ptr_ptr(opline->op2_type, &opline->op2, execute_data, &free_op2, \\1)",
"TMP" => "NULL",
"VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "NULL",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)",
);
$op1_get_zval_ptr_deref = array(
"ANY" => "get_zval_ptr_deref(opline->op1_type, &opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)",
@ -171,6 +189,24 @@ $op2_get_obj_zval_ptr = array(
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)",
);
$op1_get_obj_zval_ptr_ptr = array(
"ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "NULL",
"VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)",
);
$op2_get_obj_zval_ptr_ptr = array(
"ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, &opline->op2, execute_data, &free_op2, \\1)",
"TMP" => "NULL",
"VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)",
);
$op1_is_tmp_free = array(
"ANY" => "IS_TMP_FREE(free_op1)",
"TMP" => "1",
@ -293,7 +329,9 @@ function helper_name($name, $spec, $op1, $op2) {
function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
global $op1_type, $op2_type, $op1_get_zval_ptr, $op2_get_zval_ptr,
$op1_get_zval_ptr_deref, $op2_get_zval_ptr_deref,
$op1_get_zval_ptr_ptr, $op2_get_zval_ptr_ptr,
$op1_get_obj_zval_ptr, $op2_get_obj_zval_ptr,
$op1_get_obj_zval_ptr_ptr, $op2_get_obj_zval_ptr_ptr,
$op1_is_tmp_free, $op2_is_tmp_free, $op1_free, $op2_free,
$op1_free_op, $op2_free_op, $op1_free_op_if_var, $op2_free_op_if_var,
$op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix,
@ -310,8 +348,12 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
"/GET_OP2_ZVAL_PTR\(([^)]*)\)/",
"/GET_OP1_ZVAL_PTR_DEREF\(([^)]*)\)/",
"/GET_OP2_ZVAL_PTR_DEREF\(([^)]*)\)/",
"/GET_OP1_ZVAL_PTR_PTR\(([^)]*)\)/",
"/GET_OP2_ZVAL_PTR_PTR\(([^)]*)\)/",
"/GET_OP1_OBJ_ZVAL_PTR\(([^)]*)\)/",
"/GET_OP2_OBJ_ZVAL_PTR\(([^)]*)\)/",
"/GET_OP1_OBJ_ZVAL_PTR_PTR\(([^)]*)\)/",
"/GET_OP2_OBJ_ZVAL_PTR_PTR\(([^)]*)\)/",
"/IS_OP1_TMP_FREE\(\)/",
"/IS_OP2_TMP_FREE\(\)/",
"/FREE_OP1\(\)/",
@ -342,8 +384,12 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
$op2_get_zval_ptr[$op2],
$op1_get_zval_ptr_deref[$op1],
$op2_get_zval_ptr_deref[$op2],
$op1_get_zval_ptr_ptr[$op1],
$op2_get_zval_ptr_ptr[$op2],
$op1_get_obj_zval_ptr[$op1],
$op2_get_obj_zval_ptr[$op2],
$op1_get_obj_zval_ptr_ptr[$op1],
$op2_get_obj_zval_ptr_ptr[$op2],
$op1_is_tmp_free[$op1],
$op2_is_tmp_free[$op2],
$op1_free_op[$op1],

Loading…
Cancel
Save