summaryrefslogtreecommitdiff
path: root/Zend/zend_vm_execute.h
diff options
context:
space:
mode:
authorRasmus Lerdorf <rasmus@lerdorf.com>2015-01-30 22:57:40 -0800
committerRasmus Lerdorf <rasmus@lerdorf.com>2015-01-30 22:57:40 -0800
commit74b85316ea06c17256e102483daa472f4b638221 (patch)
treeabe0618e15fcfc93158b4239889485ffc70c4c1c /Zend/zend_vm_execute.h
parent130d7320b160443ca160ee6b3a19a034ee2c5ef1 (diff)
parent1e41295097576dbce6c197ddb7507c07ccae3cbe (diff)
downloadphp-git-dstogov-foreach.tar.gz
Merge branch 'foreach' of https://github.com/dstogov/php-src into dstogov-foreachdstogov-foreach
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r--Zend/zend_vm_execute.h1971
1 files changed, 1211 insertions, 760 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 9a7b23d87a..471f73aa32 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_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);
+ }
} 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_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);
+ }
}
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
}
@@ -3039,194 +3055,273 @@ 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, *result;
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) {
+ array_ptr = EX_CONSTANT(opline->op1);
+ 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;
+
+ 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);
}
- 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);
- }
- if (IS_CONST == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&tmp, array_ptr);
- if (Z_OPT_IMMUTABLE_P(&tmp)) {
- zval_copy_ctor_func(&tmp);
+ 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++;
}
- 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);
+ fe_ht->nInternalPointer = pos;
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos);
+
+ 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();
}
- } 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);
+
+ 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);
+ 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 {
- 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);
- }
+ 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));
}
+}
+
+static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_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;
+ HashPosition pos = 0;
+ Bucket *p;
+
+ SAVE_OPLINE();
- if (IS_CONST == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
+ if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ 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);
+ }
+ 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);
+ 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 (iter && EXPECTED(EG(exception) == NULL)) {
- ZVAL_OBJ(&iterator, &iter->std);
- array_ptr = array_ref = &iterator;
+ if (IS_CONST == IS_CONST) {
+ zval_copy_ctor_func(array_ptr);
} else {
- if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ SEPARATE_ARRAY(array_ptr);
+ }
+ fe_ht = Z_ARRVAL_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));
}
- 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, pos);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+ 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) {
- 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) {
+ 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, pos);
+ 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();
}
- }
- 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) {
+ 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();
+ }
}
- HANDLE_EXCEPTION();
- }
- iter->index = -1; /* will be set to 0 before using next handler */
- } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
- HashPosition pos = 0;
- Bucket *p;
- while (1) {
- if (pos >= fe_ht->nNumUsed) {
- is_empty = 1;
- if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ is_empty = iter->funcs->valid(iter) != SUCCESS;
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ OBJ_RELEASE(&iter->std);
+ if (IS_CONST == IS_VAR) {
+
+ } else {
}
- ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+ HANDLE_EXCEPTION();
}
- 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;
+ 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 (!ce ||
- !p->key ||
- zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
- break;
+ if (is_empty) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+ } else {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- 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;
- }
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
+ if (IS_CONST == IS_VAR) {
- if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ } else {
- }
- if (is_empty) {
+ }
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
- } else {
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
}
}
@@ -8957,194 +9052,274 @@ 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, *result;
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) {
+ array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ 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;
+
+ 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);
}
- 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);
- }
- if (IS_TMP_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&tmp, array_ptr);
- if (Z_OPT_IMMUTABLE_P(&tmp)) {
- zval_copy_ctor_func(&tmp);
+ 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++;
}
- 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);
+ fe_ht->nInternalPointer = pos;
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos);
+
+ 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();
}
- } 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);
+ zval_ptr_dtor_nogc(free_op1);
+ 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);
+
+ 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);
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
+
+ zval_ptr_dtor_nogc(free_op1);
+ if (is_empty) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} 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);
- }
+ 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));
}
+}
+
+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;
+ HashPosition pos = 0;
+ Bucket *p;
- if (ce && ce->get_iterator) {
- iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF);
+ SAVE_OPLINE();
- if (IS_TMP_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
+ if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ 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);
+ }
+ 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);
+ 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 (iter && EXPECTED(EG(exception) == NULL)) {
- ZVAL_OBJ(&iterator, &iter->std);
- array_ptr = array_ref = &iterator;
+ if (IS_TMP_VAR == IS_CONST) {
+ zval_copy_ctor_func(array_ptr);
} else {
- if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ SEPARATE_ARRAY(array_ptr);
+ }
+ fe_ht = Z_ARRVAL_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));
}
- 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, pos);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+ 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) {
- 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) {
+ 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, pos);
+
+ 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();
}
- }
- 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) {
+ 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();
+ }
}
- HANDLE_EXCEPTION();
- }
- iter->index = -1; /* will be set to 0 before using next handler */
- } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
- HashPosition pos = 0;
- Bucket *p;
- while (1) {
- if (pos >= fe_ht->nNumUsed) {
- is_empty = 1;
- if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ 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);
}
- ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+ HANDLE_EXCEPTION();
}
- 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;
+ 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 (!ce ||
- !p->key ||
- zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
- break;
+ if (is_empty) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+ } else {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- 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;
- }
-
- if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ 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) {
- }
- if (is_empty) {
+ } else {
+ zval_ptr_dtor_nogc(free_op1);
+ }
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
- } else {
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
}
}
@@ -11776,292 +11951,505 @@ 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, *result;
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) {
+ array_ptr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ 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);
}
- 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);
- }
- if (IS_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&tmp, array_ptr);
- if (Z_OPT_IMMUTABLE_P(&tmp)) {
- zval_copy_ctor_func(&tmp);
+ 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++;
}
- 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);
+ fe_ht->nInternalPointer = pos;
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos);
+
+ 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, 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();
}
- } 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);
+
+ 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();
}
}
- } else if (Z_IMMUTABLE_P(array_ref)) {
- if (IS_VAR == IS_CV) {
- zval_copy_ctor_func(array_ref);
- Z_ADDREF_P(array_ref);
+
+ 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);
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
+
+ zval_ptr_dtor_nogc(free_op1);
+ if (is_empty) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} 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);
- }
+ 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));
}
+}
- 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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *array_ptr, *array_ref;
+ HashTable *fe_ht;
+ HashPosition pos = 0;
+ Bucket *p;
- if (IS_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
- zval_ptr_dtor_nogc(free_op1);
+ SAVE_OPLINE();
+
+ if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ 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);
+ }
+
+ 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 (iter && EXPECTED(EG(exception) == NULL)) {
- ZVAL_OBJ(&iterator, &iter->std);
- array_ptr = array_ref = &iterator;
+ if (IS_VAR == IS_CONST) {
+ zval_copy_ctor_func(array_ptr);
} else {
- if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ 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;
+ 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, pos);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+ 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, pos);
+
+ 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;
- 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) {
+ 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;
- if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array_ref);
- if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ 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();
}
- HANDLE_EXCEPTION();
}
- iter->index = -1; /* will be set to 0 before using next handler */
- } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
- HashPosition pos = 0;
- Bucket *p;
+ } 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 {
+ zval_ptr_dtor_nogc(free_op1);
+ }
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+ }
+}
+
+static int ZEND_FASTCALL ZEND_FE_FETCH_R_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();
+ if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
+ fe_ht = Z_ARRVAL_P(array);
+ pos = Z_FE_POS_P(EX_VAR(opline->op1.var));
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 (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
+ /* reached end of iteration */
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)) {
+ 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 (!ce ||
- !p->key ||
- zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
- break;
+ break;
+ }
+ 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);
}
- 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;
+ 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)) {
+ 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 = 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 */
+ 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_COPY(EX_VAR(opline->result.var), 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;
+ }
+ }
+ 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 {
+ /* !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));
+ }
+ 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_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()");
- 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 (is_empty) {
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
- } else {
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
}
}
-static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_FE_FETCH_RW_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();
+ ZVAL_DEREF(array);
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 = 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 */
+ fe_ht->nInternalPointer = INVALID_IDX;
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
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));
+ 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);
- }
- 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);
- }
+ ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key);
}
- break;
}
- do {
+ 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) {
- fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
- ZEND_VM_INC_OPCODE();
- ZEND_VM_NEXT_OPCODE();
+ pos = INVALID_IDX;
+ break;
}
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;
+ if (Z_TYPE(p->val) != IS_UNDEF &&
+ (Z_TYPE(p->val) != IS_INDIRECT ||
+ Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) {
+ 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 if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
@@ -12072,93 +12460,66 @@ 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 = 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 */
+ fe_ht->nInternalPointer = INVALID_IDX;
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
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);
+ 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);
+ }
}
- do {
+ 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) {
- fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
- ZEND_VM_INC_OPCODE();
- ZEND_VM_NEXT_OPCODE();
+ pos = INVALID_IDX;
+ break;
}
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;
+ 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 {
@@ -12168,7 +12529,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,38 +12537,34 @@ 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));
- } else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- }
- if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ 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 {
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();
}
@@ -24064,194 +24421,273 @@ 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, *result;
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) {
+ array_ptr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ 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;
+
+ 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);
}
- 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);
- }
- if (IS_CV == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&tmp, array_ptr);
- if (Z_OPT_IMMUTABLE_P(&tmp)) {
- zval_copy_ctor_func(&tmp);
+ 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++;
}
- 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);
+ fe_ht->nInternalPointer = pos;
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos);
+
+ 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();
}
- } 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);
+
+ 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);
+ 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 {
- 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);
- }
+ 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));
}
+}
+
+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;
+ HashPosition pos = 0;
+ Bucket *p;
- 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 = 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);
}
- if (iter && EXPECTED(EG(exception) == NULL)) {
- ZVAL_OBJ(&iterator, &iter->std);
- array_ptr = array_ref = &iterator;
+ } else {
+ array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ }
+
+ 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);
+ 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_CV == IS_CONST) {
+ zval_copy_ctor_func(array_ptr);
} else {
- if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ SEPARATE_ARRAY(array_ptr);
+ }
+ fe_ht = Z_ARRVAL_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));
}
- 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, pos);
+
+ 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, pos);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+ 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 (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) {
+ 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();
}
- }
- 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) {
+ 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();
+ }
}
- HANDLE_EXCEPTION();
- }
- iter->index = -1; /* will be set to 0 before using next handler */
- } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
- HashPosition pos = 0;
- Bucket *p;
- while (1) {
- if (pos >= fe_ht->nNumUsed) {
- is_empty = 1;
- if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ is_empty = iter->funcs->valid(iter) != SUCCESS;
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ OBJ_RELEASE(&iter->std);
+ if (IS_CV == IS_VAR) {
+
+ } else {
}
- ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+ HANDLE_EXCEPTION();
}
- 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;
+ 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 (!ce ||
- !p->key ||
- zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
- break;
+ if (is_empty) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+ } else {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- 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;
- }
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
+ Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
+ if (IS_CV == IS_VAR) {
- if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ } else {
- }
- if (is_empty) {
+ }
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
- } else {
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
}
}
@@ -32975,6 +33411,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_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);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -38295,31 +38746,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 +38781,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 +39946,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,6 +39981,11 @@ void zend_init_opcodes_handlers(void)
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,
@@ -39525,41 +40001,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_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_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,