}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- zend_ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ 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 (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ FREE_OP1_VAR_PTR();
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
+ 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 TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
zval *array, *array_ref;
zval *value;
HashTable *fe_ht;
- zend_object_iterator *iter = NULL;
- zval *key = NULL;
+ HashPointer *ptr;
+ HashPosition pos;
+ Bucket *p;
array = array_ref = EX_VAR(opline->op1.var);
if (Z_ISREF_P(array)) {
zval_copy_ctor(array);
}
}
- if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
- key = EX_VAR((opline+1)->result.var);
- }
SAVE_OPLINE();
- switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
- default:
- case ZEND_ITER_INVALID:
- zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ 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(opline->op2.jmp_addr);
-
- case ZEND_ITER_PLAIN_OBJECT: {
- zend_object *zobj = Z_OBJ_P(array);
- int key_type;
- zend_string *str_key;
- zend_ulong int_key;
-
- fe_ht = Z_OBJPROP_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
+ } 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 (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
+ while (1) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
+ /* reached end of iteration */
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(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 if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(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();
+ }
+ 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;
+ 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 TSRMLS_CC)) == NULL) {
+ /* plain object */
+ 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(opline->op2.jmp_addr);
+ } 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 (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
while (1) {
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (Z_TYPE_P(value) == IS_INDIRECT) {
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
value = Z_INDIRECT_P(value);
- if (Z_TYPE_P(value) == IS_UNDEF) {
- zend_hash_move_forward(fe_ht);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
continue;
}
}
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
-
- zend_hash_move_forward(fe_ht);
- if (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ 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 TSRMLS_CC) == SUCCESS) {
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ if (p->key->val[0]) {
+ if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(p->key)++;
+ }
+ } else {
+ const char *class_name, *prop_name;
+ int prop_name_len;
+ zend_unmangle_property_name_ex(
+ p->key->val, p->key->len, &class_name, &prop_name, &prop_name_len);
+ ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len);
+ }
+ }
break;
}
+ pos++;
}
-
- if (key) {
- if (key_type == HASH_KEY_IS_LONG) {
- ZVAL_LONG(key, int_key);
- } else {
- const char *class_name, *prop_name;
- int prop_name_len;
- zend_unmangle_property_name_ex(
- str_key->val, (int)str_key->len, &class_name, &prop_name, &prop_name_len
- );
- ZVAL_STRINGL(key, prop_name, prop_name_len);
- }
- }
-
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
- }
-
- case ZEND_ITER_PLAIN_ARRAY:
- fe_ht = Z_ARRVAL_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
- /* reached end of iteration */
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
- if (key) {
- zend_hash_get_current_key_zval(fe_ht, key);
+ 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);
}
- zend_hash_move_forward(fe_ht);
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
-
- case ZEND_ITER_OBJECT:
+ do {
+ pos++;
+ if (pos >= fe_ht->nNumUsed) {
+ fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ 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 TSRMLS_CC) == FAILURE));
+ fe_ht->nInternalPointer = ptr->pos = pos;
+ ptr->h = fe_ht->arData[pos].h;
+ 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.
/* failure in get_current_data */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (key) {
+ 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 (iter->funcs->get_current_key) {
- iter->funcs->get_current_key(iter, key TSRMLS_CC);
+ iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var) TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(array_ref);
HANDLE_EXCEPTION();
}
} else {
- ZVAL_LONG(key, iter->index);
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index);
}
}
- break;
- }
-
- 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));
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
-
- CHECK_EXCEPTION();
- ZEND_VM_INC_OPCODE();
- ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- zend_ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ 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_RESET_VARIABLE) {
+
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ 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 TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- zend_ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ 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_RESET_VARIABLE) {
+
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ 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 TSRMLS_CC) == SUCCESS) {
+ break;
}
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- zend_ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ 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_VAR == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ 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 TSRMLS_CC) == SUCCESS) {
+ break;
}
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
zval *array, *array_ref;
zval *value;
HashTable *fe_ht;
- zend_object_iterator *iter = NULL;
- zval *key = NULL;
+ HashPointer *ptr;
+ HashPosition pos;
+ Bucket *p;
array = array_ref = EX_VAR(opline->op1.var);
if (Z_ISREF_P(array)) {
zval_copy_ctor(array);
}
}
- if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
- key = EX_VAR((opline+1)->result.var);
- }
SAVE_OPLINE();
- switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
- default:
- case ZEND_ITER_INVALID:
- zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ 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(opline->op2.jmp_addr);
+ } 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 (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
+ while (1) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
+ /* reached end of iteration */
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(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 if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(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();
+ }
+ 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;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
+ zend_object_iterator *iter;
- case ZEND_ITER_PLAIN_OBJECT: {
- zend_object *zobj = Z_OBJ_P(array);
- int key_type;
- zend_string *str_key;
- zend_ulong int_key;
+ if ((iter = zend_iterator_unwrap(array TSRMLS_CC)) == NULL) {
+ /* plain object */
+ zend_object *zobj = Z_OBJ_P(array);
- fe_ht = Z_OBJPROP_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
+ 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(opline->op2.jmp_addr);
+ } 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 (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
while (1) {
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (Z_TYPE_P(value) == IS_INDIRECT) {
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
value = Z_INDIRECT_P(value);
- if (Z_TYPE_P(value) == IS_UNDEF) {
- zend_hash_move_forward(fe_ht);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
continue;
}
}
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
-
- zend_hash_move_forward(fe_ht);
- if (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ 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 TSRMLS_CC) == SUCCESS) {
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ if (p->key->val[0]) {
+ if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(p->key)++;
+ }
+ } else {
+ const char *class_name, *prop_name;
+ int prop_name_len;
+ zend_unmangle_property_name_ex(
+ p->key->val, p->key->len, &class_name, &prop_name, &prop_name_len);
+ ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len);
+ }
+ }
break;
}
+ pos++;
}
-
- if (key) {
- if (key_type == HASH_KEY_IS_LONG) {
- ZVAL_LONG(key, int_key);
- } else {
- const char *class_name, *prop_name;
- int prop_name_len;
- zend_unmangle_property_name_ex(
- str_key->val, (int)str_key->len, &class_name, &prop_name, &prop_name_len
- );
- ZVAL_STRINGL(key, prop_name, prop_name_len);
- }
- }
-
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
- }
-
- case ZEND_ITER_PLAIN_ARRAY:
- fe_ht = Z_ARRVAL_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
- /* reached end of iteration */
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
- if (key) {
- zend_hash_get_current_key_zval(fe_ht, key);
+ 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);
}
- zend_hash_move_forward(fe_ht);
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
-
- case ZEND_ITER_OBJECT:
+ do {
+ pos++;
+ if (pos >= fe_ht->nNumUsed) {
+ fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ 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 TSRMLS_CC) == FAILURE));
+ fe_ht->nInternalPointer = ptr->pos = pos;
+ ptr->h = fe_ht->arData[pos].h;
+ 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.
/* failure in get_current_data */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (key) {
+ 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 (iter->funcs->get_current_key) {
- iter->funcs->get_current_key(iter, key TSRMLS_CC);
+ iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var) TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(array_ref);
HANDLE_EXCEPTION();
}
} else {
- ZVAL_LONG(key, iter->index);
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index);
}
}
- break;
- }
-
- 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));
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
-
- CHECK_EXCEPTION();
- ZEND_VM_INC_OPCODE();
- ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- zend_ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ 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_RESET_VARIABLE) {
+
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ 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 TSRMLS_CC) == SUCCESS) {
+ break;
}
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;