From 4638f7b91407c48710007af82a68da0007c820f2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 28 Jan 2015 07:43:28 +0300 Subject: Change "foreach" statement behavior (this is just a PoC yet) - "foreach by value" don't relay on internal array/object pointer and doesnt perform array duplication. It just locks it incrementing reference counter. If the original array is modified by some code, the copy on write is performed and "foreach" still work with the old copy. - it makes no difference if array given to "foreach by value" is reference itself - "foreach by reference" still use internal array/object pointer and should work similar to PHP-5. (This id not completely implemented) --- Zend/zend_vm_execute.h | 1489 +++++++++++++++++++++++++----------------------- 1 file changed, 767 insertions(+), 722 deletions(-) (limited to 'Zend/zend_vm_execute.h') diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9a7b23d87a..a51941195c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3039,194 +3039,178 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref, iterator, tmp; + zval *array_ptr; HashTable *fe_ht; - zend_object_iterator *iter = NULL; - zend_class_entry *ce = NULL; - zend_bool is_empty = 0; SAVE_OPLINE(); - if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && - (opline->extended_value & ZEND_FE_FETCH_BYREF)) { - array_ptr = array_ref = NULL; - ZVAL_DEREF(array_ptr); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); - if (!Z_ISREF_P(array_ref)) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce->get_iterator == NULL) { - Z_ADDREF_P(array_ptr); + array_ptr = EX_CONSTANT(opline->op1); + ZVAL_DEREF(array_ptr); + if (IS_CONST != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } - array_ref = array_ptr; - } else { - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } - } else { - array_ptr = array_ref = EX_CONSTANT(opline->op1); - if (IS_CONST & (IS_VAR|IS_CV)) { - ZVAL_DEREF(array_ptr); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } - if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&tmp, array_ptr); - if (Z_OPT_IMMUTABLE_P(&tmp)) { - zval_copy_ctor_func(&tmp); - } - array_ref = array_ptr = &tmp; - if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce && ce->get_iterator) { - Z_DELREF_P(array_ref); - } - } - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (!ce->get_iterator) { - if (IS_CONST == IS_CV) { - Z_ADDREF_P(array_ref); - } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } - } else if (Z_IMMUTABLE_P(array_ref)) { - if (IS_CONST == IS_CV) { - zval_copy_ctor_func(array_ref); - Z_ADDREF_P(array_ref); - } else { - ZVAL_COPY_VALUE(&tmp, array_ref); - zval_copy_ctor_func(&tmp); - array_ptr = array_ref = &tmp; - } - } else if (Z_REFCOUNTED_P(array_ref)) { - if (IS_CONST == IS_CONST || - (IS_CONST == IS_CV && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 1) || - (IS_CONST == IS_VAR && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 2)) { - if (IS_CONST == IS_VAR) { - Z_DELREF_P(array_ref); - } - ZVAL_DUP(&tmp, array_ref); - array_ptr = array_ref = &tmp; - } else if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { - if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { - ZVAL_UNREF(array_ref); - array_ptr = array_ref; - } - if (Z_IMMUTABLE_P(array_ptr)) { - zval_copy_ctor_func(array_ptr); - } else if (Z_ISREF_P(array_ref) && - Z_COPYABLE_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1) { - Z_DELREF_P(array_ptr); - zval_copy_ctor_func(array_ptr); - } - if (IS_CONST == IS_CV) { - Z_ADDREF_P(array_ref); - } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; + + if (UNEXPECTED(EG(exception) != NULL)) { + + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { + if (IS_CONST != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ptr)) { + Z_ADDREF_P(array_ptr); } } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); + Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } +} - if (ce && ce->get_iterator) { - iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF); +static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *array_ptr, *array_ref; + HashTable *fe_ht; - if (IS_CONST == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { + SAVE_OPLINE(); + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + array_ref = NULL; + ZVAL_MAKE_REF(array_ref); + array_ptr = Z_REFVAL_P(array_ref); + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + SEPARATE_ARRAY(array_ptr); } - if (iter && EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(&iterator, &iter->std); - array_ptr = array_ref = &iterator; - } else { - if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + } else { + array_ref = array_ptr = EX_CONSTANT(opline->op1); + } + + if (IS_CONST != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } zend_throw_exception_internal(NULL); HANDLE_EXCEPTION(); } - } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - - if (iter) { iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } } + is_empty = iter->funcs->valid(iter) != SUCCESS; + if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); HashPosition pos = 0; Bucket *p; + if (IS_CONST != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ref)) { + Z_ADDREF_P(array_ref); + } + } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { - is_empty = 1; - if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; - if (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { - pos++; - continue; - } - if (!ce || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) { + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (Z_TYPE_P(array_ptr) != IS_OBJECT || + !p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { break; } pos++; } - fe_ht->nInternalPointer = pos; - ptr->pos = pos; - ptr->ht = fe_ht; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - is_empty = 0; + Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - is_empty = 1; - } + ZVAL_UNDEF(EX_VAR(opline->result.var)); - if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - - } - if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } } @@ -8957,194 +8941,178 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *array_ptr, *array_ref, iterator, tmp; + zval *array_ptr; HashTable *fe_ht; - zend_object_iterator *iter = NULL; - zend_class_entry *ce = NULL; - zend_bool is_empty = 0; SAVE_OPLINE(); - if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && - (opline->extended_value & ZEND_FE_FETCH_BYREF)) { - array_ptr = array_ref = NULL; - ZVAL_DEREF(array_ptr); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); - if (!Z_ISREF_P(array_ref)) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce->get_iterator == NULL) { - Z_ADDREF_P(array_ptr); + array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + ZVAL_DEREF(array_ptr); + if (IS_TMP_VAR != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } - array_ref = array_ptr; - } else { - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } - } else { - array_ptr = array_ref = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR & (IS_VAR|IS_CV)) { - ZVAL_DEREF(array_ptr); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } - if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&tmp, array_ptr); - if (Z_OPT_IMMUTABLE_P(&tmp)) { - zval_copy_ctor_func(&tmp); - } - array_ref = array_ptr = &tmp; - if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce && ce->get_iterator) { - Z_DELREF_P(array_ref); - } - } - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (!ce->get_iterator) { - if (IS_TMP_VAR == IS_CV) { - Z_ADDREF_P(array_ref); - } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } - } else if (Z_IMMUTABLE_P(array_ref)) { - if (IS_TMP_VAR == IS_CV) { - zval_copy_ctor_func(array_ref); - Z_ADDREF_P(array_ref); - } else { - ZVAL_COPY_VALUE(&tmp, array_ref); - zval_copy_ctor_func(&tmp); - array_ptr = array_ref = &tmp; - } - } else if (Z_REFCOUNTED_P(array_ref)) { - if (IS_TMP_VAR == IS_CONST || - (IS_TMP_VAR == IS_CV && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 1) || - (IS_TMP_VAR == IS_VAR && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 2)) { - if (IS_TMP_VAR == IS_VAR) { - Z_DELREF_P(array_ref); - } - ZVAL_DUP(&tmp, array_ref); - array_ptr = array_ref = &tmp; - } else if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { - if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { - ZVAL_UNREF(array_ref); - array_ptr = array_ref; - } - if (Z_IMMUTABLE_P(array_ptr)) { - zval_copy_ctor_func(array_ptr); - } else if (Z_ISREF_P(array_ref) && - Z_COPYABLE_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1) { - Z_DELREF_P(array_ptr); - zval_copy_ctor_func(array_ptr); - } - if (IS_TMP_VAR == IS_CV) { - Z_ADDREF_P(array_ref); - } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; + + if (UNEXPECTED(EG(exception) != NULL)) { + + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { + if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ptr)) { + Z_ADDREF_P(array_ptr); } } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); + Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } +} - if (ce && ce->get_iterator) { - iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF); +static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *array_ptr, *array_ref; + HashTable *fe_ht; - if (IS_TMP_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { + SAVE_OPLINE(); + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + array_ref = NULL; + ZVAL_MAKE_REF(array_ref); + array_ptr = Z_REFVAL_P(array_ref); + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + SEPARATE_ARRAY(array_ptr); } - if (iter && EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(&iterator, &iter->std); - array_ptr = array_ref = &iterator; - } else { - if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + } else { + array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + } + + if (IS_TMP_VAR != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } zend_throw_exception_internal(NULL); HANDLE_EXCEPTION(); } - } - - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - if (iter) { iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } } + is_empty = iter->funcs->valid(iter) != SUCCESS; + if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); HashPosition pos = 0; Bucket *p; + if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ref)) { + Z_ADDREF_P(array_ref); + } + } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { - is_empty = 1; - if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; - if (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { - pos++; - continue; - } - if (!ce || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) { + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (Z_TYPE_P(array_ptr) != IS_OBJECT || + !p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { break; } pos++; } - fe_ht->nInternalPointer = pos; - ptr->pos = pos; - ptr->ht = fe_ht; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - is_empty = 0; + Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - is_empty = 1; - } - - if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } } @@ -11776,245 +11744,200 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *array_ptr, *array_ref, iterator, tmp; + zval *array_ptr; HashTable *fe_ht; - zend_object_iterator *iter = NULL; - zend_class_entry *ce = NULL; - zend_bool is_empty = 0; SAVE_OPLINE(); - if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && - (opline->extended_value & ZEND_FE_FETCH_BYREF)) { - array_ptr = array_ref = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_DEREF(array_ptr); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); - if (!Z_ISREF_P(array_ref)) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce->get_iterator == NULL) { - Z_ADDREF_P(array_ptr); + array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + ZVAL_DEREF(array_ptr); + if (IS_VAR != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(free_op1); + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } - array_ref = array_ptr; - } else { - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } - } else { - array_ptr = array_ref = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR & (IS_VAR|IS_CV)) { - ZVAL_DEREF(array_ptr); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } - if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&tmp, array_ptr); - if (Z_OPT_IMMUTABLE_P(&tmp)) { - zval_copy_ctor_func(&tmp); - } - array_ref = array_ptr = &tmp; - if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce && ce->get_iterator) { - Z_DELREF_P(array_ref); - } - } - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (!ce->get_iterator) { - if (IS_VAR == IS_CV) { - Z_ADDREF_P(array_ref); - } - } - } else if (Z_IMMUTABLE_P(array_ref)) { - if (IS_VAR == IS_CV) { - zval_copy_ctor_func(array_ref); - Z_ADDREF_P(array_ref); - } else { - ZVAL_COPY_VALUE(&tmp, array_ref); - zval_copy_ctor_func(&tmp); - array_ptr = array_ref = &tmp; - } - } else if (Z_REFCOUNTED_P(array_ref)) { - if (IS_VAR == IS_CONST || - (IS_VAR == IS_CV && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 1) || - (IS_VAR == IS_VAR && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 2)) { - if (IS_VAR == IS_VAR) { - Z_DELREF_P(array_ref); - } - ZVAL_DUP(&tmp, array_ref); - array_ptr = array_ref = &tmp; - } else if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { - if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { - ZVAL_UNREF(array_ref); - array_ptr = array_ref; - } - if (Z_IMMUTABLE_P(array_ptr)) { - zval_copy_ctor_func(array_ptr); - } else if (Z_ISREF_P(array_ref) && - Z_COPYABLE_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1) { - Z_DELREF_P(array_ptr); - zval_copy_ctor_func(array_ptr); - } - if (IS_VAR == IS_CV) { - Z_ADDREF_P(array_ref); - } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(free_op1); + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } } - } - if (ce && ce->get_iterator) { - iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF); + is_empty = iter->funcs->valid(iter) != SUCCESS; - if (IS_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { + if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op1); + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } - if (iter && EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(&iterator, &iter->std); - array_ptr = array_ref = &iterator; + iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + + zval_ptr_dtor_nogc(free_op1); + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { + if (IS_VAR != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ptr)) { + Z_ADDREF_P(array_ptr); } + } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); + Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *array_ptr, *array_ref; + HashTable *fe_ht; + + SAVE_OPLINE(); + + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + array_ref = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + ZVAL_MAKE_REF(array_ref); + array_ptr = Z_REFVAL_P(array_ref); + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + SEPARATE_ARRAY(array_ptr); + } + } else { + array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + } + + if (IS_VAR != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } zend_throw_exception_internal(NULL); HANDLE_EXCEPTION(); } - } - - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - if (iter) { iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } } + is_empty = iter->funcs->valid(iter) != SUCCESS; + if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); HashPosition pos = 0; Bucket *p; + if (IS_VAR != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ref)) { + Z_ADDREF_P(array_ref); + } + } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { - is_empty = 1; - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; - if (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { - pos++; - continue; - } - if (!ce || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) { + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (Z_TYPE_P(array_ptr) != IS_OBJECT || + !p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { break; } pos++; } - fe_ht->nInternalPointer = pos; - ptr->pos = pos; - ptr->ht = fe_ht; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - is_empty = 0; - } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - is_empty = 1; - } + Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); - if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array, *array_ref; + zval *array; zval *value; HashTable *fe_ht; - HashPointer *ptr; HashPosition pos; Bucket *p; - array = array_ref = EX_VAR(opline->op1.var); - if (Z_ISREF_P(array)) { - array = Z_REFVAL_P(array); - // TODO: referenced value might be changed to different array ??? - if (Z_IMMUTABLE_P(array)) { - zval_copy_ctor_func(array); - } - } - + array = EX_VAR(opline->op1.var); SAVE_OPLINE(); - if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { fe_ht = Z_ARRVAL_P(array); - ptr = (HashPointer*)EX_VAR((opline+1)->op1.var); - pos = ptr->pos; - if (UNEXPECTED(pos == INVALID_IDX)) { - /* reached end of iteration */ - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else if (UNEXPECTED(ptr->ht != fe_ht)) { - ptr->ht = fe_ht; - pos = 0; - } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) { - if (fe_ht->u.flags & HASH_FLAG_PACKED) { - pos = ptr->h; - } else { - pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (1) { - if (pos == INVALID_IDX) { - pos = fe_ht->nInternalPointer; - break; - } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { - break; - } - pos = Z_NEXT(fe_ht->arData[pos].val); - } - } - } + pos = Z_FE_POS_P(EX_VAR(opline->op1.var)); while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ @@ -12022,46 +11945,27 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } p = fe_ht->arData + pos; value = &p->val; - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + if (Z_TYPE_P(value) == IS_UNDEF) { pos++; continue; - } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { + } else if (Z_TYPE_P(value) == IS_INDIRECT) { value = Z_INDIRECT_P(value); - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + if (Z_TYPE_P(value) == IS_UNDEF) { pos++; continue; } } - if (opline->extended_value & ZEND_FE_FETCH_BYREF) { - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); - } else { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { - if (!p->key) { - ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); - } - } break; } - do { - pos++; - if (pos >= fe_ht->nNumUsed) { - fe_ht->nInternalPointer = ptr->pos = INVALID_IDX; - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); + if (opline->extended_value) { + if (!p->key) { + ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); } - p = fe_ht->arData + pos; - } while (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)); - fe_ht->nInternalPointer = ptr->pos = pos; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; + } + ZVAL_COPY(EX_VAR(opline->result.var), value); + Z_FE_POS_P(EX_VAR(opline->op1.var)) = pos + 1; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { @@ -12072,30 +11976,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_object *zobj = Z_OBJ_P(array); fe_ht = Z_OBJPROP_P(array); - ptr = (HashPointer*)EX_VAR((opline+1)->op1.var); - pos = ptr->pos; - if (pos == INVALID_IDX) { - /* reached end of iteration */ - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else if (UNEXPECTED(ptr->ht != fe_ht)) { - ptr->ht = fe_ht; - pos = 0; - } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) { - if (fe_ht->u.flags & HASH_FLAG_PACKED) { - pos = ptr->h; - } else { - pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (1) { - if (pos == INVALID_IDX) { - pos = fe_ht->nInternalPointer; - break; - } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { - break; - } - pos = Z_NEXT(fe_ht->arData[pos].val); - } - } - } + pos = Z_FE_POS_P(EX_VAR(opline->op1.var)); while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ @@ -12104,61 +11985,37 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG p = fe_ht->arData + pos; value = &p->val; - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + if (Z_TYPE_P(value) == IS_UNDEF) { pos++; continue; - } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { + } else if (Z_TYPE_P(value) == IS_INDIRECT) { value = Z_INDIRECT_P(value); - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + if (Z_TYPE_P(value) == IS_UNDEF) { pos++; continue; } } - - if (UNEXPECTED(!p->key)) { - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { - ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); - } - break; - } else if (zend_check_property_access(zobj, p->key) == SUCCESS) { - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { - if (p->key->val[0]) { - ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); - } else { - const char *class_name, *prop_name; - size_t prop_name_len; - zend_unmangle_property_name_ex( - p->key, &class_name, &prop_name, &prop_name_len); - ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len); - } - } + if (!p->key || + zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS) { break; } pos++; } - if (opline->extended_value & ZEND_FE_FETCH_BYREF) { - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); - } else { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - do { - pos++; - if (pos >= fe_ht->nNumUsed) { - fe_ht->nInternalPointer = ptr->pos = INVALID_IDX; - ZEND_VM_INC_OPCODE(); - ZEND_VM_NEXT_OPCODE(); + if (opline->extended_value) { + if (UNEXPECTED(!p->key)) { + ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); + } else if (p->key->val[0]) { + ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); + } else { + const char *class_name, *prop_name; + size_t prop_name_len; + zend_unmangle_property_name_ex( + p->key, &class_name, &prop_name, &prop_name_len); + ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len); } - p = fe_ht->arData + pos; - } while (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) || - (EXPECTED(p->key != NULL) && - zend_check_property_access(zobj, p->key) == FAILURE)); - fe_ht->nInternalPointer = ptr->pos = pos; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; + } + ZVAL_COPY(EX_VAR(opline->result.var), value); + Z_FE_POS_P(EX_VAR(opline->op1.var)) = pos + 1; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else { @@ -12168,7 +12025,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG * In case that ever happens we need an additional flag. */ iter->funcs->move_forward(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); + zval_ptr_dtor(array); HANDLE_EXCEPTION(); } } @@ -12176,32 +12033,236 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (!iter || (iter->index > 0 && iter->funcs->valid(iter) == FAILURE)) { /* reached end of iteration */ if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); + zval_ptr_dtor(array); HANDLE_EXCEPTION(); } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } value = iter->funcs->get_current_data(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); + zval_ptr_dtor(array); HANDLE_EXCEPTION(); } if (!value) { /* failure in get_current_data */ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - if (opline->extended_value & ZEND_FE_FETCH_BYREF) { - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); + ZVAL_COPY(EX_VAR(opline->result.var), value); + if (opline->extended_value) { + if (iter->funcs->get_current_key) { + iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var)); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array); + HANDLE_EXCEPTION(); + } + } else { + ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index); + } + } + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); + } + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *array; + zval *value; + HashTable *fe_ht; + HashPosition pos; + Bucket *p; + + array = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + + ZVAL_DEREF(array); + if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { + fe_ht = Z_ARRVAL_P(array); + pos = Z_FE_POS_P(EX_VAR(opline->op1.var)); + if (UNEXPECTED(pos == INVALID_IDX)) { + /* reached end of iteration */ + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + if (Z_PTR_P(EX_VAR((opline+1)->op1.var)) != fe_ht) { + pos = fe_ht->nInternalPointer; + } + SEPARATE_ARRAY(array); + fe_ht = Z_ARRVAL_P(array); + Z_PTR_P(EX_VAR((opline+1)->op1.var)) = fe_ht; + } +//??? if (pos != fe_ht->nInternalPointer) { +//??? //... +//??? } + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + fe_ht->nInternalPointer = INVALID_IDX; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + value = &p->val; + if (Z_TYPE_P(value) == IS_UNDEF) { + pos++; + continue; + } else if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) == IS_UNDEF) { + pos++; + continue; + } + } + break; + } + if (opline->extended_value) { + if (!p->key) { + ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); } else { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); + } + } + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); + while (1) { + pos++; + if (pos >= fe_ht->nNumUsed) { + pos = INVALID_IDX; + break; + } + p = fe_ht->arData + pos; + if (Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) { + break; + } + } + Z_FE_POS_P(EX_VAR(opline->op1.var)) = fe_ht->nInternalPointer = pos; + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { + zend_object_iterator *iter; + + if ((iter = zend_iterator_unwrap(array)) == NULL) { + /* plain object */ + zend_object *zobj = Z_OBJ_P(array); + + fe_ht = Z_OBJPROP_P(array); + pos = Z_FE_POS_P(EX_VAR(opline->op1.var)); + if (UNEXPECTED(pos == INVALID_IDX)) { + /* reached end of iteration */ + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + if (Z_PTR_P(EX_VAR((opline+1)->op1.var)) != fe_ht) { + pos = fe_ht->nInternalPointer; + } + Z_PTR_P(EX_VAR((opline+1)->op1.var)) = fe_ht; + } +//??? if (pos != fe_ht->nInternalPointer) { +//??? +//??? } + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + fe_ht->nInternalPointer = INVALID_IDX; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + p = fe_ht->arData + pos; + value = &p->val; + if (Z_TYPE_P(value) == IS_UNDEF) { + pos++; + continue; + } else if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) == IS_UNDEF) { + pos++; + continue; + } + } + if (!p->key || + zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS) { + break; + } + pos++; + } + if (opline->extended_value) { + if (UNEXPECTED(!p->key)) { + ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h); + } else if (p->key->val[0]) { + ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key); + } else { + const char *class_name, *prop_name; + size_t prop_name_len; + zend_unmangle_property_name_ex( + p->key, &class_name, &prop_name, &prop_name_len); + ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len); + } + } + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); + while (1) { + pos++; + if (pos >= fe_ht->nNumUsed) { + pos = INVALID_IDX; + break; + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (Z_TYPE_P(array) != IS_OBJECT || + !p->key || + zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) { + break; + } + } + Z_FE_POS_P(EX_VAR(opline->op1.var)) = fe_ht->nInternalPointer = pos; + ZEND_VM_INC_OPCODE(); + ZEND_VM_NEXT_OPCODE(); + } else { + /* !iter happens from exception */ + if (iter && ++iter->index > 0) { + /* This could cause an endless loop if index becomes zero again. + * In case that ever happens we need an additional flag. */ + iter->funcs->move_forward(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array); + HANDLE_EXCEPTION(); + } + } + /* If index is zero we come from FE_RESET and checked valid() already. */ + if (!iter || (iter->index > 0 && iter->funcs->valid(iter) == FAILURE)) { + /* reached end of iteration */ + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array); + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { + value = iter->funcs->get_current_data(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor(array); + HANDLE_EXCEPTION(); + } + if (!value) { + /* failure in get_current_data */ + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); + if (opline->extended_value) { if (iter->funcs->get_current_key) { iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var)); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); + zval_ptr_dtor(array); HANDLE_EXCEPTION(); } } else { @@ -24064,194 +24125,178 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref, iterator, tmp; + zval *array_ptr; HashTable *fe_ht; - zend_object_iterator *iter = NULL; - zend_class_entry *ce = NULL; - zend_bool is_empty = 0; SAVE_OPLINE(); - if ((IS_CV == IS_CV || IS_CV == IS_VAR) && - (opline->extended_value & ZEND_FE_FETCH_BYREF)) { - array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - ZVAL_DEREF(array_ptr); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); - if (!Z_ISREF_P(array_ref)) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce->get_iterator == NULL) { - Z_ADDREF_P(array_ptr); + array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + ZVAL_DEREF(array_ptr); + if (IS_CV != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } - array_ref = array_ptr; - } else { - if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); - } - } else { - array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - if (IS_CV & (IS_VAR|IS_CV)) { - ZVAL_DEREF(array_ptr); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } - if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&tmp, array_ptr); - if (Z_OPT_IMMUTABLE_P(&tmp)) { - zval_copy_ctor_func(&tmp); - } - array_ref = array_ptr = &tmp; - if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (ce && ce->get_iterator) { - Z_DELREF_P(array_ref); - } - } - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - ce = Z_OBJCE_P(array_ptr); - if (!ce->get_iterator) { - if (IS_CV == IS_CV) { - Z_ADDREF_P(array_ref); - } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } - } else if (Z_IMMUTABLE_P(array_ref)) { - if (IS_CV == IS_CV) { - zval_copy_ctor_func(array_ref); - Z_ADDREF_P(array_ref); - } else { - ZVAL_COPY_VALUE(&tmp, array_ref); - zval_copy_ctor_func(&tmp); - array_ptr = array_ref = &tmp; - } - } else if (Z_REFCOUNTED_P(array_ref)) { - if (IS_CV == IS_CONST || - (IS_CV == IS_CV && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 1) || - (IS_CV == IS_VAR && - !Z_ISREF_P(array_ref) && - Z_REFCOUNT_P(array_ref) > 2)) { - if (IS_CV == IS_VAR) { - Z_DELREF_P(array_ref); - } - ZVAL_DUP(&tmp, array_ref); - array_ptr = array_ref = &tmp; - } else if (IS_CV == IS_CV || IS_CV == IS_VAR) { - if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) { - ZVAL_UNREF(array_ref); - array_ptr = array_ref; - } - if (Z_IMMUTABLE_P(array_ptr)) { - zval_copy_ctor_func(array_ptr); - } else if (Z_ISREF_P(array_ref) && - Z_COPYABLE_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1) { - Z_DELREF_P(array_ptr); - zval_copy_ctor_func(array_ptr); - } - if (IS_CV == IS_CV) { - Z_ADDREF_P(array_ref); - } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; + + if (UNEXPECTED(EG(exception) != NULL)) { + + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { + if (IS_CV != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ptr)) { + Z_ADDREF_P(array_ptr); } } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); + Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } +} + +static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE - if (ce && ce->get_iterator) { - iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF); + zval *array_ptr, *array_ref; + HashTable *fe_ht; - if (IS_CV == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) { + SAVE_OPLINE(); + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + ZVAL_MAKE_REF(array_ref); + array_ptr = Z_REFVAL_P(array_ref); + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + SEPARATE_ARRAY(array_ptr); } - if (iter && EXPECTED(EG(exception) == NULL)) { - ZVAL_OBJ(&iterator, &iter->std); - array_ptr = array_ref = &iterator; - } else { - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { + } else { + array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + } + + if (IS_CV != IS_CONST && + Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } zend_throw_exception_internal(NULL); HANDLE_EXCEPTION(); } - } - - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - if (iter) { iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } } + is_empty = iter->funcs->valid(iter) != SUCCESS; + if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor(array_ref); - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } + OBJ_RELEASE(&iter->std); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var); HashPosition pos = 0; Bucket *p; + if (IS_CV != IS_TMP_VAR) { + if (Z_REFCOUNTED_P(array_ref)) { + Z_ADDREF_P(array_ref); + } + } + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { - is_empty = 1; - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; - if (Z_TYPE(p->val) == IS_UNDEF || - (Z_TYPE(p->val) == IS_INDIRECT && - Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) { - pos++; - continue; - } - if (!ce || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) { + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (Z_TYPE_P(array_ptr) != IS_OBJECT || + !p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { break; } pos++; } - fe_ht->nInternalPointer = pos; - ptr->pos = pos; - ptr->ht = fe_ht; - ptr->h = fe_ht->arData[pos].h; - ptr->key = fe_ht->arData[pos].key; - is_empty = 0; + Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; + ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - is_empty = 1; - } + ZVAL_UNDEF(EX_VAR(opline->result.var)); - if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) { - - } - if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } } @@ -38295,31 +38340,31 @@ void zend_init_opcodes_handlers(void) ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER, - ZEND_FE_RESET_SPEC_CONST_HANDLER, - ZEND_FE_RESET_SPEC_CONST_HANDLER, - ZEND_FE_RESET_SPEC_CONST_HANDLER, - ZEND_FE_RESET_SPEC_CONST_HANDLER, - ZEND_FE_RESET_SPEC_CONST_HANDLER, - ZEND_FE_RESET_SPEC_TMP_HANDLER, - ZEND_FE_RESET_SPEC_TMP_HANDLER, - ZEND_FE_RESET_SPEC_TMP_HANDLER, - ZEND_FE_RESET_SPEC_TMP_HANDLER, - ZEND_FE_RESET_SPEC_TMP_HANDLER, - ZEND_FE_RESET_SPEC_VAR_HANDLER, - ZEND_FE_RESET_SPEC_VAR_HANDLER, - ZEND_FE_RESET_SPEC_VAR_HANDLER, - ZEND_FE_RESET_SPEC_VAR_HANDLER, - ZEND_FE_RESET_SPEC_VAR_HANDLER, + ZEND_FE_RESET_R_SPEC_CONST_HANDLER, + ZEND_FE_RESET_R_SPEC_CONST_HANDLER, + ZEND_FE_RESET_R_SPEC_CONST_HANDLER, + ZEND_FE_RESET_R_SPEC_CONST_HANDLER, + ZEND_FE_RESET_R_SPEC_CONST_HANDLER, + ZEND_FE_RESET_R_SPEC_TMP_HANDLER, + ZEND_FE_RESET_R_SPEC_TMP_HANDLER, + ZEND_FE_RESET_R_SPEC_TMP_HANDLER, + ZEND_FE_RESET_R_SPEC_TMP_HANDLER, + ZEND_FE_RESET_R_SPEC_TMP_HANDLER, + ZEND_FE_RESET_R_SPEC_VAR_HANDLER, + ZEND_FE_RESET_R_SPEC_VAR_HANDLER, + ZEND_FE_RESET_R_SPEC_VAR_HANDLER, + ZEND_FE_RESET_R_SPEC_VAR_HANDLER, + ZEND_FE_RESET_R_SPEC_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_FE_RESET_SPEC_CV_HANDLER, - ZEND_FE_RESET_SPEC_CV_HANDLER, - ZEND_FE_RESET_SPEC_CV_HANDLER, - ZEND_FE_RESET_SPEC_CV_HANDLER, - ZEND_FE_RESET_SPEC_CV_HANDLER, + ZEND_FE_RESET_R_SPEC_CV_HANDLER, + ZEND_FE_RESET_R_SPEC_CV_HANDLER, + ZEND_FE_RESET_R_SPEC_CV_HANDLER, + ZEND_FE_RESET_R_SPEC_CV_HANDLER, + ZEND_FE_RESET_R_SPEC_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -38330,11 +38375,11 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_FE_FETCH_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -39495,11 +39540,31 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER, ZEND_NULL_HANDLER, + ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, + ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, + ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, + ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, + ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, + ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, + ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, + ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, + ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, + ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, + ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, + ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, + ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, + ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, + ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_FE_RESET_RW_SPEC_CV_HANDLER, + ZEND_FE_RESET_RW_SPEC_CV_HANDLER, + ZEND_FE_RESET_RW_SPEC_CV_HANDLER, + ZEND_FE_RESET_RW_SPEC_CV_HANDLER, + ZEND_FE_RESET_RW_SPEC_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -39510,31 +39575,11 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, + ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, -- cgit v1.2.1 From dd2a36a2074bbb0cb31de00b66dcf2812d6d753f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 28 Jan 2015 10:02:34 +0300 Subject: Use GET_OP1_ZVAL_PTR_DEREF() (IS_TMP_VAR and IS_CONST can't be IS_REFERENCE) --- Zend/zend_vm_execute.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'Zend/zend_vm_execute.h') diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a51941195c..3eead75c73 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3049,7 +3049,6 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); array_ptr = EX_CONSTANT(opline->op1); - ZVAL_DEREF(array_ptr); if (IS_CONST != IS_CONST && Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { zend_class_entry *ce = Z_OBJCE_P(array_ptr); @@ -8951,7 +8950,6 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - ZVAL_DEREF(array_ptr); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { zend_class_entry *ce = Z_OBJCE_P(array_ptr); @@ -11753,8 +11751,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); - array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_DEREF(array_ptr); + array_ptr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); if (IS_VAR != IS_CONST && Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { zend_class_entry *ce = Z_OBJCE_P(array_ptr); @@ -24134,8 +24131,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); - array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - ZVAL_DEREF(array_ptr); + array_ptr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var); if (IS_CV != IS_CONST && Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { zend_class_entry *ce = Z_OBJCE_P(array_ptr); -- cgit v1.2.1 From 92e90c09f085c22707ff4a59201f016f56e0ef8b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 28 Jan 2015 12:44:57 +0300 Subject: Fixed operand destruction in case of exceptions in iterator --- Zend/zend_vm_execute.h | 178 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 131 insertions(+), 47 deletions(-) (limited to 'Zend/zend_vm_execute.h') diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3eead75c73..3d0dd2e97d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3068,8 +3068,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } } @@ -3077,8 +3077,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -3092,13 +3092,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_CONST != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -3137,7 +3137,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_CONST == IS_VAR) { + } else { + + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -3149,8 +3153,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CONST == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } } @@ -3158,8 +3166,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CONST == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -3168,6 +3180,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + if (IS_CONST == IS_VAR) { + + } else { + + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -3208,7 +3225,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_CONST == IS_VAR) { + + } else { + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -8957,7 +8978,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - + zval_ptr_dtor_nogc(free_op1); if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -8969,8 +8990,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } } @@ -8978,14 +8999,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + zval_ptr_dtor_nogc(free_op1); if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -8993,13 +9015,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -9038,7 +9060,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_TMP_VAR == IS_VAR) { + } else { + zval_ptr_dtor_nogc(free_op1); + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -9050,8 +9076,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } } @@ -9059,8 +9089,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -9069,6 +9103,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -9109,7 +9148,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_TMP_VAR == IS_VAR) { + } else { + zval_ptr_dtor_nogc(free_op1); + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -11771,8 +11814,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } } @@ -11780,8 +11823,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -11796,13 +11839,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); @@ -11842,7 +11885,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -11854,8 +11901,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; OBJ_RELEASE(&iter->std); + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } } @@ -11863,8 +11914,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; OBJ_RELEASE(&iter->std); + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -11873,7 +11928,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -11915,7 +11974,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -12252,9 +12315,6 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ /* failure in get_current_data */ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); if (opline->extended_value) { if (iter->funcs->get_current_key) { iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var)); @@ -12266,6 +12326,9 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index); } } + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } @@ -24151,8 +24214,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } } @@ -24160,8 +24223,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -24175,13 +24238,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_CV != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -24220,7 +24283,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_CV == IS_VAR) { + + } else { + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -24232,8 +24299,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CV == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } } @@ -24241,8 +24312,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CV == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -24251,6 +24326,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + if (IS_CV == IS_VAR) { + + } else { + + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -24291,7 +24371,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_CV == IS_VAR) { + + } else { + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -- cgit v1.2.1 From eef80c583762d1e98d177cdbb27e3a8a6b0c4539 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 28 Jan 2015 16:52:21 +0300 Subject: Fixed foreach by reference iteration over constant array --- Zend/zend_vm_execute.h | 116 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 80 insertions(+), 36 deletions(-) (limited to 'Zend/zend_vm_execute.h') diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3d0dd2e97d..362f450390 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3120,11 +3120,9 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { - array_ref = NULL; - ZVAL_MAKE_REF(array_ref); - array_ptr = Z_REFVAL_P(array_ref); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); + array_ref = array_ptr = NULL; + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); } } else { array_ref = array_ptr = EX_CONSTANT(opline->op1); @@ -3195,12 +3193,25 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE HashPosition pos = 0; Bucket *p; - if (IS_CONST != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ref)) { - Z_ADDREF_P(array_ref); + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + if (IS_CONST == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); } + fe_ht = Z_ARRVAL_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { @@ -9043,11 +9054,9 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { - array_ref = NULL; - ZVAL_MAKE_REF(array_ref); - array_ptr = Z_REFVAL_P(array_ref); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); + array_ref = array_ptr = NULL; + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); } } else { array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); @@ -9118,12 +9127,25 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ HashPosition pos = 0; Bucket *p; - if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ref)) { - Z_ADDREF_P(array_ref); + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + if (IS_TMP_VAR == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); + } + fe_ht = Z_ARRVAL_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { @@ -11868,11 +11890,9 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - array_ref = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - ZVAL_MAKE_REF(array_ref); - array_ptr = Z_REFVAL_P(array_ref); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); + array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); } } else { array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -11943,12 +11963,25 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ HashPosition pos = 0; Bucket *p; - if (IS_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ref)) { - Z_ADDREF_P(array_ref); + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + if (IS_VAR == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); + } + fe_ht = Z_ARRVAL_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; @@ -24266,11 +24299,9 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); if (IS_CV == IS_VAR || IS_CV == IS_CV) { - array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - ZVAL_MAKE_REF(array_ref); - array_ptr = Z_REFVAL_P(array_ref); - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - SEPARATE_ARRAY(array_ptr); + array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); } } else { array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); @@ -24341,12 +24372,25 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A HashPosition pos = 0; Bucket *p; - if (IS_CV != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ref)) { - Z_ADDREF_P(array_ref); + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_TYPE_P(array_ptr) == IS_ARRAY) { + if (IS_CV == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); } + fe_ht = Z_ARRVAL_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); while (1) { if (pos >= fe_ht->nNumUsed) { -- cgit v1.2.1 From 15a23b1218b3e38630d677751a975907daa2cd54 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 29 Jan 2015 21:05:02 +0300 Subject: Reimplement iteration magic with HashTableIterators (see https://wiki.php.net/rfc/php7_foreach#implementation_details) --- Zend/zend_vm_execute.h | 123 +++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 56 deletions(-) (limited to 'Zend/zend_vm_execute.h') diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 362f450390..4244f5f750 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1347,6 +1347,14 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } + } else if (brk_opline->opcode == ZEND_FE_FREE) { + if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { + zval *var = EX_VAR(brk_opline->op1.var); + if (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_END_SILENCE) { /* restore previous error_reporting value */ if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) { @@ -1805,6 +1813,14 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } + } else if (brk_opline->opcode == ZEND_FE_FREE) { + if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { + zval *var = EX_VAR(brk_opline->op1.var); + if (Z_FE_ITER_P(var) != (uint32_t)-1) { + zend_hash_iterator_del(Z_FE_ITER_P(var)); + } + zval_ptr_dtor_nogc(var); + } } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1)); } @@ -3175,8 +3191,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE iter->index = -1; /* will be set to 0 before using next handler */ ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_CONST == IS_VAR) { @@ -3215,6 +3230,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE while (1) { if (pos >= fe_ht->nNumUsed) { + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; @@ -3228,14 +3244,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE } pos++; } - Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_CONST == IS_VAR) { } else { @@ -9109,8 +9126,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ iter->index = -1; /* will be set to 0 before using next handler */ ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_TMP_VAR == IS_VAR) { @@ -9149,6 +9165,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ while (1) { if (pos >= fe_ht->nNumUsed) { + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; @@ -9162,14 +9179,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ } pos++; } - Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_TMP_VAR == IS_VAR) { } else { @@ -11945,8 +11963,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ iter->index = -1; /* will be set to 0 before using next handler */ ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_VAR == IS_VAR) { if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; @@ -11985,6 +12002,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ while (1) { if (pos >= fe_ht->nNumUsed) { if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; @@ -11998,8 +12016,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } pos++; } - Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -12007,6 +12025,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_VAR == IS_VAR) { if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { @@ -12177,21 +12196,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_DEREF(array); if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { fe_ht = Z_ARRVAL_P(array); - pos = Z_FE_POS_P(EX_VAR(opline->op1.var)); - if (UNEXPECTED(pos == INVALID_IDX)) { - /* reached end of iteration */ - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - if (Z_PTR_P(EX_VAR((opline+1)->op1.var)) != fe_ht) { - pos = fe_ht->nInternalPointer; - } - SEPARATE_ARRAY(array); - fe_ht = Z_ARRVAL_P(array); - Z_PTR_P(EX_VAR((opline+1)->op1.var)) = fe_ht; - } -//??? if (pos != fe_ht->nInternalPointer) { -//??? //... -//??? } + pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht); while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ @@ -12235,7 +12240,8 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ break; } } - Z_FE_POS_P(EX_VAR(opline->op1.var)) = fe_ht->nInternalPointer = pos; + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = + fe_ht->nInternalPointer = pos; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { @@ -12246,19 +12252,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zend_object *zobj = Z_OBJ_P(array); fe_ht = Z_OBJPROP_P(array); - pos = Z_FE_POS_P(EX_VAR(opline->op1.var)); - if (UNEXPECTED(pos == INVALID_IDX)) { - /* reached end of iteration */ - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - if (Z_PTR_P(EX_VAR((opline+1)->op1.var)) != fe_ht) { - pos = fe_ht->nInternalPointer; - } - Z_PTR_P(EX_VAR((opline+1)->op1.var)) = fe_ht; - } -//??? if (pos != fe_ht->nInternalPointer) { -//??? -//??? } + pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht); while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ @@ -12316,7 +12310,8 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ break; } } - Z_FE_POS_P(EX_VAR(opline->op1.var)) = fe_ht->nInternalPointer = pos; + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = + fe_ht->nInternalPointer = pos; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else { @@ -24354,8 +24349,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A iter->index = -1; /* will be set to 0 before using next handler */ ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_CV == IS_VAR) { @@ -24394,6 +24388,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A while (1) { if (pos >= fe_ht->nNumUsed) { + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; @@ -24407,14 +24402,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A } pos++; } - Z_FE_POS_P(EX_VAR(opline->result.var)) = fe_ht->nInternalPointer = pos; - ZVAL_PTR(EX_VAR((opline+2)->op1.var), fe_ht); + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_CV == IS_VAR) { } else { @@ -33144,6 +33140,21 @@ static int ZEND_FASTCALL ZEND_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FE_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *var; + USE_OPLINE + + SAVE_OPLINE(); + var = EX_VAR(opline->op1.var); + if (Z_FE_ITER_P(var) != (uint32_t)-1) { + zend_hash_iterator_del(Z_FE_ITER_P(var)); + } + zval_ptr_dtor_nogc(var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -39719,16 +39730,16 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, -- cgit v1.2.1 From 5aa9712b0a30303aadfe3bdd8ae1f072ca3e6ba1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 30 Jan 2015 09:49:35 +0300 Subject: Implement consistent behavior for foreach by value over plain object --- Zend/zend_vm_execute.h | 1239 +++++++++++++++++++++++++++++------------------- 1 file changed, 755 insertions(+), 484 deletions(-) (limited to 'Zend/zend_vm_execute.h') diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4244f5f750..8ae97d2bf8 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1350,7 +1350,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER } else if (brk_opline->opcode == ZEND_FE_FREE) { if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { zval *var = EX_VAR(brk_opline->op1.var); - if (Z_FE_ITER_P(var) != (uint32_t)-1) { + 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); @@ -1816,7 +1816,7 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else if (brk_opline->opcode == ZEND_FE_FREE) { if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { zval *var = EX_VAR(brk_opline->op1.var); - if (Z_FE_ITER_P(var) != (uint32_t)-1) { + 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); @@ -3059,68 +3059,102 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER { USE_OPLINE - zval *array_ptr; + zval *array_ptr, *result; HashTable *fe_ht; SAVE_OPLINE(); array_ptr = EX_CONSTANT(opline->op1); - if (IS_CONST != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); - zend_bool is_empty; + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + HashPosition pos = 0; + Bucket *p; + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CONST != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + fe_ht = Z_OBJPROP_P(array_ptr); + pos = 0; + while (1) { + if (pos >= fe_ht->nNumUsed) { - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); HANDLE_EXCEPTION(); } - } - is_empty = iter->funcs->valid(iter) != SUCCESS; + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); + } + } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ + is_empty = iter->funcs->valid(iter) != SUCCESS; - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - zval *result = EX_VAR(opline->result.var); + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(array_ptr); - } - Z_FE_POS_P(result) = 0; + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -3132,6 +3166,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE zval *array_ptr, *array_ref; HashTable *fe_ht; + HashPosition pos = 0; + Bucket *p; SAVE_OPLINE(); @@ -3144,70 +3180,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE array_ref = array_ptr = EX_CONSTANT(opline->op1); } - if (IS_CONST != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); - zend_bool is_empty; - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (IS_CONST == IS_VAR) { - - } else { - - } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); - } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } - - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_CONST == IS_VAR) { - - } else { - - } - HANDLE_EXCEPTION(); - } - } - - is_empty = iter->funcs->valid(iter) != SUCCESS; - - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_CONST == IS_VAR) { - - } else { - - } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ - - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - - if (IS_CONST == IS_VAR) { - - } else { - - } - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPosition pos = 0; - Bucket *p; - + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { if (array_ptr == array_ref) { ZVAL_NEW_REF(array_ref, array_ref); @@ -3219,14 +3192,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE array_ptr = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(array_ptr, array_ref); } - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - if (IS_CONST == IS_CONST) { - zval_copy_ctor_func(array_ptr); - } else { - SEPARATE_ARRAY(array_ptr); - } - fe_ht = Z_ARRVAL_P(array_ptr); + if (IS_CONST == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); } + fe_ht = Z_ARRVAL_P(array_ptr); while (1) { if (pos >= fe_ht->nNumUsed) { @@ -3234,12 +3205,9 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; - if ((Z_TYPE(p->val) != IS_UNDEF && - (Z_TYPE(p->val) != IS_INDIRECT || - Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && - (Z_TYPE_P(array_ptr) != IS_OBJECT || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + if (Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) { break; } pos++; @@ -3249,6 +3217,101 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); + } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + fe_ht = Z_OBJPROP_P(array_ptr); + while (1) { + if (pos >= fe_ht->nNumUsed) { + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; + } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_CONST == IS_VAR) { + + } else { + + } + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + if (IS_CONST == IS_VAR) { + + } else { + + } + HANDLE_EXCEPTION(); + } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; + + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + if (IS_CONST == IS_VAR) { + + } else { + + } + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + + if (IS_CONST == IS_VAR) { + + } else { + + } + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -8993,69 +9056,103 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A { USE_OPLINE zend_free_op free_op1; - zval *array_ptr; + zval *array_ptr, *result; HashTable *fe_ht; SAVE_OPLINE(); array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - if (IS_TMP_VAR != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); - zend_bool is_empty; + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(free_op1); - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + HashPosition pos = 0; + Bucket *p; + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_TMP_VAR != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + fe_ht = Z_OBJPROP_P(array_ptr); + pos = 0; + while (1) { + if (pos >= fe_ht->nNumUsed) { + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { zval_ptr_dtor_nogc(free_op1); + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); HANDLE_EXCEPTION(); } - } - is_empty = iter->funcs->valid(iter) != SUCCESS; + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + } - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ + is_empty = iter->funcs->valid(iter) != SUCCESS; - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ - zval_ptr_dtor_nogc(free_op1); - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - zval *result = EX_VAR(opline->result.var); + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(array_ptr); + zval_ptr_dtor_nogc(free_op1); + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } - Z_FE_POS_P(result) = 0; - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; zval_ptr_dtor_nogc(free_op1); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -9067,6 +9164,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zend_free_op free_op1; zval *array_ptr, *array_ref; HashTable *fe_ht; + HashPosition pos = 0; + Bucket *p; SAVE_OPLINE(); @@ -9079,70 +9178,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); } - if (IS_TMP_VAR != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); - zend_bool is_empty; - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (IS_TMP_VAR == IS_VAR) { - - } else { - zval_ptr_dtor_nogc(free_op1); - } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); - } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } - - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_TMP_VAR == IS_VAR) { - - } else { - zval_ptr_dtor_nogc(free_op1); - } - HANDLE_EXCEPTION(); - } - } - - is_empty = iter->funcs->valid(iter) != SUCCESS; - - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_TMP_VAR == IS_VAR) { - - } else { - zval_ptr_dtor_nogc(free_op1); - } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ - - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - - if (IS_TMP_VAR == IS_VAR) { - - } else { - zval_ptr_dtor_nogc(free_op1); - } - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPosition pos = 0; - Bucket *p; - + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { if (array_ptr == array_ref) { ZVAL_NEW_REF(array_ref, array_ref); @@ -9154,14 +9190,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ array_ptr = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(array_ptr, array_ref); } - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - if (IS_TMP_VAR == IS_CONST) { - zval_copy_ctor_func(array_ptr); - } else { - SEPARATE_ARRAY(array_ptr); - } - fe_ht = Z_ARRVAL_P(array_ptr); + if (IS_TMP_VAR == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); } + fe_ht = Z_ARRVAL_P(array_ptr); while (1) { if (pos >= fe_ht->nNumUsed) { @@ -9169,12 +9203,9 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; - if ((Z_TYPE(p->val) != IS_UNDEF && - (Z_TYPE(p->val) != IS_INDIRECT || - Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && - (Z_TYPE_P(array_ptr) != IS_OBJECT || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + if (Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) { break; } pos++; @@ -9184,6 +9215,101 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + fe_ht = Z_OBJPROP_P(array_ptr); + while (1) { + if (pos >= fe_ht->nNumUsed) { + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; + } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } + HANDLE_EXCEPTION(); + } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; + + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -11829,70 +11955,105 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A { USE_OPLINE zend_free_op free_op1; - zval *array_ptr; + zval *array_ptr, *result; HashTable *fe_ht; SAVE_OPLINE(); array_ptr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - if (IS_VAR != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); - zend_bool is_empty; + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; + + zval_ptr_dtor_nogc(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + HashPosition pos = 0; + Bucket *p; + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_VAR != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + fe_ht = Z_OBJPROP_P(array_ptr); + pos = 0; + while (1) { + if (pos >= fe_ht->nNumUsed) { + zval_ptr_dtor_nogc(free_op1); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; + } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { zval_ptr_dtor_nogc(free_op1); - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(free_op1); + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; + if (UNEXPECTED(EG(exception) != NULL)) { OBJ_RELEASE(&iter->std); zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } - } + iter->index = -1; /* will be set to 0 before using next handler */ - is_empty = iter->funcs->valid(iter) != SUCCESS; + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ - - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - - zval_ptr_dtor_nogc(free_op1); - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - zval *result = EX_VAR(opline->result.var); - - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(array_ptr); + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } - Z_FE_POS_P(result) = 0; - - zval_ptr_dtor_nogc(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; zval_ptr_dtor_nogc(free_op1); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -11904,6 +12065,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zend_free_op free_op1; zval *array_ptr, *array_ref; HashTable *fe_ht; + HashPosition pos = 0; + Bucket *p; SAVE_OPLINE(); @@ -11916,28 +12079,114 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); } - if (IS_VAR != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); - zend_bool is_empty; - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (IS_VAR == IS_VAR) { + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (IS_VAR == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); + } + fe_ht = Z_ARRVAL_P(array_ptr); + while (1) { + if (pos >= fe_ht->nNumUsed) { if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } else { - zval_ptr_dtor_nogc(free_op1); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + p = fe_ht->arData + pos; + if (Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) { + break; } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); + pos++; } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + fe_ht = Z_OBJPROP_P(array_ptr); + while (1) { + if (pos >= fe_ht->nNumUsed) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; + } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } + HANDLE_EXCEPTION(); + } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { OBJ_RELEASE(&iter->std); if (IS_VAR == IS_VAR) { @@ -11947,81 +12196,23 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } HANDLE_EXCEPTION(); } - } + iter->index = -1; /* will be set to 0 before using next handler */ - is_empty = iter->funcs->valid(iter) != SUCCESS; + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); if (IS_VAR == IS_VAR) { if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { zval_ptr_dtor_nogc(free_op1); } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ - - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - - if (IS_VAR == IS_VAR) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - } else { - zval_ptr_dtor_nogc(free_op1); - } - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPosition pos = 0; - Bucket *p; - - if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - if (array_ptr == array_ref) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - Z_ADDREF_P(array_ref); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - } else { - array_ptr = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(array_ptr, array_ref); - } - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - if (IS_VAR == IS_CONST) { - zval_copy_ctor_func(array_ptr); - } else { - SEPARATE_ARRAY(array_ptr); - } - fe_ht = Z_ARRVAL_P(array_ptr); - } - while (1) { - if (pos >= fe_ht->nNumUsed) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); } - p = fe_ht->arData + pos; - if ((Z_TYPE(p->val) != IS_UNDEF && - (Z_TYPE(p->val) != IS_INDIRECT || - Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && - (Z_TYPE_P(array_ptr) != IS_OBJECT || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { - break; - } - pos++; } - fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -12088,7 +12279,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A zend_object *zobj = Z_OBJ_P(array); fe_ht = Z_OBJPROP_P(array); - pos = Z_FE_POS_P(EX_VAR(opline->op1.var)); + pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht); while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ @@ -12127,7 +12318,24 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A } } ZVAL_COPY(EX_VAR(opline->result.var), value); - Z_FE_POS_P(EX_VAR(opline->op1.var)) = pos + 1; + while (1) { + pos++; + if (pos >= fe_ht->nNumUsed) { + pos = INVALID_IDX; + break; + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (Z_TYPE_P(array) != IS_OBJECT || + !p->key || + zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) { + break; + } + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = + fe_ht->nInternalPointer = pos; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else { @@ -24217,68 +24425,102 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR { USE_OPLINE - zval *array_ptr; + zval *array_ptr, *result; HashTable *fe_ht; SAVE_OPLINE(); array_ptr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var); - if (IS_CV != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); - zend_bool is_empty; + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + HashPosition pos = 0; + Bucket *p; + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CV != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + fe_ht = Z_OBJPROP_P(array_ptr); + pos = 0; + while (1) { + if (pos >= fe_ht->nNumUsed) { - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); + zend_bool is_empty; + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); HANDLE_EXCEPTION(); } - } - is_empty = iter->funcs->valid(iter) != SUCCESS; + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); + } + } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ + is_empty = iter->funcs->valid(iter) != SUCCESS; - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - zval *result = EX_VAR(opline->result.var); + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(array_ptr); - } - Z_FE_POS_P(result) = 0; + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -24290,6 +24532,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A zval *array_ptr, *array_ref; HashTable *fe_ht; + HashPosition pos = 0; + Bucket *p; SAVE_OPLINE(); @@ -24302,70 +24546,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); } - if (IS_CV != IS_CONST && - Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJCE_P(array_ptr)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); - zend_bool is_empty; - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (IS_CV == IS_VAR) { - - } else { - - } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); - } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } - - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_CV == IS_VAR) { - - } else { - - } - HANDLE_EXCEPTION(); - } - } - - is_empty = iter->funcs->valid(iter) != SUCCESS; - - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_CV == IS_VAR) { - - } else { - - } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ - - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - - if (IS_CV == IS_VAR) { - - } else { - - } - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } - } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - HashPosition pos = 0; - Bucket *p; - + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { if (IS_CV == IS_VAR || IS_CV == IS_CV) { if (array_ptr == array_ref) { ZVAL_NEW_REF(array_ref, array_ref); @@ -24377,14 +24558,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A array_ptr = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(array_ptr, array_ref); } - if (Z_TYPE_P(array_ptr) == IS_ARRAY) { - if (IS_CV == IS_CONST) { - zval_copy_ctor_func(array_ptr); - } else { - SEPARATE_ARRAY(array_ptr); - } - fe_ht = Z_ARRVAL_P(array_ptr); + if (IS_CV == IS_CONST) { + zval_copy_ctor_func(array_ptr); + } else { + SEPARATE_ARRAY(array_ptr); } + fe_ht = Z_ARRVAL_P(array_ptr); while (1) { if (pos >= fe_ht->nNumUsed) { @@ -24392,12 +24571,9 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } p = fe_ht->arData + pos; - if ((Z_TYPE(p->val) != IS_UNDEF && - (Z_TYPE(p->val) != IS_INDIRECT || - Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && - (Z_TYPE_P(array_ptr) != IS_OBJECT || - !p->key || - zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + if (Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) { break; } pos++; @@ -24407,6 +24583,101 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + fe_ht = Z_OBJPROP_P(array_ptr); + while (1) { + if (pos >= fe_ht->nNumUsed) { + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + p = fe_ht->arData + pos; + if ((Z_TYPE(p->val) != IS_UNDEF && + (Z_TYPE(p->val) != IS_INDIRECT || + Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) && + (!p->key || + zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) { + break; + } + pos++; + } + fe_ht->nInternalPointer = pos; + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_class_entry *ce = Z_OBJCE_P(array_ptr); + zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); + zend_bool is_empty; + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_CV == IS_VAR) { + + } else { + + } + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); + } + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + if (IS_CV == IS_VAR) { + + } else { + + } + HANDLE_EXCEPTION(); + } + } + + is_empty = iter->funcs->valid(iter) != SUCCESS; + + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + if (IS_CV == IS_VAR) { + + } else { + + } + HANDLE_EXCEPTION(); + } + iter->index = -1; /* will be set to 0 before using next handler */ + + ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + + if (IS_CV == IS_VAR) { + + } else { + + } + if (is_empty) { + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + } } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -33147,7 +33418,7 @@ static int ZEND_FASTCALL ZEND_FE_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); var = EX_VAR(opline->op1.var); - if (Z_FE_ITER_P(var) != (uint32_t)-1) { + 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); -- cgit v1.2.1 From 1e41295097576dbce6c197ddb7507c07ccae3cbe Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sat, 31 Jan 2015 07:28:58 +0300 Subject: Generalize HashTableIterator API to allows its usage without iinvolvement of HashTable.nInternalPonter --- Zend/zend_vm_execute.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'Zend/zend_vm_execute.h') diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8ae97d2bf8..471f73aa32 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3104,7 +3104,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -3213,7 +3213,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -3248,7 +3248,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -9101,7 +9101,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -9211,7 +9211,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -9246,7 +9246,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12001,7 +12001,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); @@ -12112,7 +12112,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -12148,7 +12148,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -24470,7 +24470,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -24579,7 +24579,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -24614,7 +24614,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A pos++; } fe_ht->nInternalPointer = pos; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); -- cgit v1.2.1