43 new_call = zend_vm_stack_push_call_frame(
49 new_call->extra_named_params =
call->extra_named_params;
50 new_call->prev_execute_data = prev_call;
55 generator->execute_data->call = prev_call;
84 used_stack -= frame_size;
88 new_call =
call->prev_execute_data;
89 zend_vm_stack_free_call_frame(
call);
114static void zend_generator_cleanup_unfinished_execution(
228 return check_node_running_in_fiber(
generator->node.child.single);
233 if (check_node_running_in_fiber(child)) {
241static void zend_generator_dtor_storage(
zend_object *
object)
246 uint32_t op_num, try_catch_offset;
258 if (current_generator->
flags & ZEND_GENERATOR_IN_FIBER) {
259 if (check_node_running_in_fiber(
generator)) {
261 generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
274 zend_generator_remove_child(&parent->node,
generator);
283 ||
CG(unclean_shutdown)) {
288 op_num =
ex->opline -
ex->func->op_array.opcodes;
289 try_catch_offset = -1;
292 for (i = 0; i <
ex->func->op_array.last_try_catch; i++) {
294 if (op_num < try_catch->try_op) {
297 if (op_num < try_catch->catch_op || op_num < try_catch->finally_end) {
298 try_catch_offset = i;
303 while (try_catch_offset != (uint32_t) -1) {
306 if (op_num < try_catch->finally_op) {
313 const zend_op *old_opline_before_exception =
EG(opline_before_exception);
319 ex->opline = &
ex->func->op_array.opcodes[try_catch->
finally_op] - 1;
320 generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
324 EG(opline_before_exception) = old_opline_before_exception;
335 }
else if (op_num < try_catch->finally_end) {
358static void zend_generator_free_storage(
zend_object *
object)
390 zend_get_gc_buffer_add_zval(gc_buffer, &
generator->value);
391 zend_get_gc_buffer_add_zval(gc_buffer, &
generator->key);
392 zend_get_gc_buffer_add_zval(gc_buffer, &
generator->retval);
393 zend_get_gc_buffer_add_zval(gc_buffer, &
generator->values);
397 call = zend_generator_revert_call_stack(
generator->frozen_call_stack);
403 zend_generator_revert_call_stack(
call);
407 zend_get_gc_buffer_add_obj(gc_buffer, &
generator->node.parent->std);
421 zend_get_gc_buffer_add_zval(gc_buffer, &
generator->value);
422 zend_get_gc_buffer_add_zval(gc_buffer, &
generator->key);
423 zend_get_gc_buffer_add_zval(gc_buffer, &
generator->retval);
425 zend_get_gc_buffer_use(gc_buffer, table,
n);
435 if (
generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING) {
447 zend_get_gc_buffer_use(gc_buffer, table,
n);
459 generator->largest_used_integer_key = -1;
476 zend_throw_error(
NULL,
"The \"Generator\" class is reserved for internal use and cannot be manually instantiated");
489 while (
generator->node.parent->node.parent) {
507 EG(current_execute_data) =
generator->execute_data;
513 zend_rethrow_exception(
EG(current_execute_data));
535 zend_hash_index_add_new_ptr(
ht,
555 zend_generator_add_child(from,
generator);
556 generator->flags |= ZEND_GENERATOR_DO_INIT;
566 clear_link_to_leaf(root);
584 while (
generator->node.parent->execute_data) {
605 zend_generator_remove_child(&new_root_parent->
node, new_root);
627 if (!(old_root->
flags & ZEND_GENERATOR_CURRENTLY_RUNNING)) {
631 return zend_generator_get_current(
generator);
698 if (iter->
index++ > 0) {
750 if (
generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING) {
757 orig_generator->
flags &= ~ZEND_GENERATOR_DO_INIT;
762 orig_generator->
flags |= ZEND_GENERATOR_IN_FIBER;
763 generator->flags |= ZEND_GENERATOR_IN_FIBER;
767 orig_generator->
flags &= ~ZEND_GENERATOR_AT_FIRST_YIELD;
771 uint32_t original_jit_trace_num =
EG(jit_trace_num);
774 EG(current_execute_data) =
generator->execute_data;
775 EG(jit_trace_num) = 0;
794 EG(jit_trace_num) = original_jit_trace_num;
796 orig_generator->
flags &= ~(ZEND_GENERATOR_DO_INIT | ZEND_GENERATOR_IN_FIBER);
797 generator->flags &= ~ZEND_GENERATOR_IN_FIBER;
818 || (
generator->flags & ZEND_GENERATOR_FORCED_CLOSE));
820 generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING;
831 generator->flags &= ~(ZEND_GENERATOR_CURRENTLY_RUNNING | ZEND_GENERATOR_IN_FIBER);
842 EG(jit_trace_num) = original_jit_trace_num;
851 if (!
EG(current_execute_data)) {
853 }
else if (
EG(current_execute_data)->
func &&
855 zend_rethrow_exception(
EG(current_execute_data));
858 generator = zend_generator_get_current(orig_generator);
860 orig_generator->
flags &= ~ZEND_GENERATOR_DO_INIT;
867 generator = zend_generator_get_current(orig_generator);
871 orig_generator->
flags &= ~(ZEND_GENERATOR_DO_INIT | ZEND_GENERATOR_IN_FIBER);
879 generator->flags |= ZEND_GENERATOR_AT_FIRST_YIELD;
886 zend_generator_ensure_initialized(
generator);
888 if (!(
generator->flags & ZEND_GENERATOR_AT_FIRST_YIELD)) {
916 zend_generator_ensure_initialized(
generator);
933 zend_generator_ensure_initialized(
generator);
935 root = zend_generator_get_current(
generator);
951 zend_generator_ensure_initialized(
generator);
953 root = zend_generator_get_current(
generator);
969 zend_generator_ensure_initialized(
generator);
987 zend_generator_ensure_initialized(
generator);
994 root = zend_generator_get_current(
generator);
996 if (root->
send_target && !(root->
flags & ZEND_GENERATOR_CURRENTLY_RUNNING)) {
1002 root = zend_generator_get_current(
generator);
1023 zend_generator_ensure_initialized(
generator);
1028 zend_generator_throw_exception(root,
exception);
1032 root = zend_generator_get_current(
generator);
1053 zend_generator_ensure_initialized(
generator);
1061 "Cannot get return value of a generator that hasn't returned", 0);
1082 if (
func->common.scope) {
1110 zend_generator_ensure_initialized(
generator);
1122 zend_generator_ensure_initialized(
generator);
1124 root = zend_generator_get_current(
generator);
1126 return &root->
value;
1134 zend_generator_ensure_initialized(
generator);
1136 root = zend_generator_get_current(
generator);
1152 zend_generator_ensure_initialized(
generator);
1166static HashTable *zend_generator_iterator_get_gc(
1169 *table = &iterator->
data;
1175 zend_generator_iterator_dtor,
1176 zend_generator_iterator_valid,
1177 zend_generator_iterator_get_data,
1178 zend_generator_iterator_get_key,
1179 zend_generator_iterator_move_forward,
1180 zend_generator_iterator_rewind,
1182 zend_generator_iterator_get_gc,
1197 zend_throw_exception(
NULL,
"You can only iterate a generator by-reference if it declared that it yields by-reference", 0);
1204 iterator->
funcs = &zend_generator_iterator_functions;
1220 zend_generator_handlers.free_obj = zend_generator_free_storage;
1221 zend_generator_handlers.dtor_obj = zend_generator_dtor_storage;
1222 zend_generator_handlers.get_gc = zend_generator_get_gc;
1223 zend_generator_handlers.clone_obj =
NULL;
1224 zend_generator_handlers.get_constructor = zend_generator_get_constructor;
prev(array|object &$array)
memset(ptr, 0, type->size)
unsigned const char * pos
unsigned char key[REFLECTION_KEY_LEN]
zend_test_fiber * active_fiber
zend_execute_data * original_execute_data
zend_execute_data * prev_execute_data
union _zend_generator_node::@240302224373203254241357377177253207307263372347 child
union _zend_generator_node::@232312244065232141030257143346267306240210334326 ptr
zend_execute_data execute_fake
zend_execute_data * execute_data
void(* get_current_key)(zend_object_iterator *iter, zval *key)
void(* move_forward)(zend_object_iterator *iter)
zend_result(* valid)(zend_object_iterator *iter)
zval *(* get_current_data)(zend_object_iterator *iter)
const zend_object_iterator_funcs * funcs
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
#define RETURN_COPY_DEREF(zv)
#define ZEND_PARSE_PARAMETERS_END()
#define ZEND_PARSE_PARAMETERS_NONE()
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
#define ZEND_METHOD(classname, name)
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce)
#define Z_PARAM_ZVAL(dest)
#define ZEND_CLOSURE_OBJECT(op_array)
#define ZEND_USER_CODE(type)
#define ZEND_CALL_ALLOCATED
#define ZEND_CALL_FRAME_SLOT
#define ZEND_CALL_VAR(call, n)
#define ZEND_CALL_HAS_SYMBOL_TABLE
struct _zend_op_array zend_op_array
#define ZEND_CALL_HAS_EXTRA_NAMED_PARAMS
#define ZEND_CALL_NUM_ARGS(call)
#define ZEND_CALL_INFO(call)
#define ZEND_ACC_HAS_FINALLY_BLOCK
struct _zend_try_catch_element zend_try_catch_element
#define ZEND_CALL_RELEASE_THIS
#define ZEND_ACC_RETURN_REFERENCE
ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception)
ZEND_API zend_class_entry * zend_ce_exception
ZEND_API ZEND_COLD void zend_throw_exception_object(zval *exception)
ZEND_API ZEND_COLD zend_object * zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
ZEND_API zend_class_entry * zend_ce_throwable
void zend_exception_set_previous(zend_object *exception, zend_object *add_previous)
ZEND_API void ZEND_FASTCALL zend_free_extra_named_params(zend_array *extra_named_params)
ZEND_API HashTable * zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield)
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table)
ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num)
ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data)
ZEND_API void(* zend_execute_ex)(zend_execute_data *execute_data)
union _zend_function zend_function
ZEND_API zend_get_gc_buffer * zend_get_gc_buffer_create(void)
void zend_register_generator_ce(void)
ZEND_API void zend_generator_resume(zend_generator *orig_generator)
ZEND_API zend_generator * zend_generator_update_current(zend_generator *generator)
ZEND_API zend_generator * zend_generator_update_root(zend_generator *generator)
HashTable * zend_generator_frame_gc(zend_get_gc_buffer *gc_buffer, zend_generator *generator)
ZEND_API void zend_generator_close(zend_generator *generator, bool finished_execution)
ZEND_API void zend_generator_restore_call_stack(zend_generator *generator)
ZEND_API zend_class_entry * zend_ce_ClosedGeneratorException
ZEND_API zend_execute_data * zend_generator_freeze_call_stack(zend_execute_data *execute_data)
void zend_generator_yield_from(zend_generator *generator, zend_generator *from)
ZEND_API zend_execute_data * zend_generator_check_placeholder_frame(zend_execute_data *ptr)
ZEND_API zend_class_entry * zend_ce_generator
struct _zend_generator zend_generator
struct _zend_generator_node zend_generator_node
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
ZEND_API zval *ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key, zval *pData)
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
#define ZEND_HASH_FOREACH_PTR(ht, _ptr)
#define ZEND_HASH_FOREACH_END()
ZEND_API zend_class_entry * zend_ce_iterator
ZEND_API void zend_iterator_init(zend_object_iterator *iter)
struct _zend_object_iterator zend_object_iterator
struct _zend_object_iterator_funcs zend_object_iterator_funcs
struct _zend_string zend_string
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API void ZEND_FASTCALL zend_observer_generator_resume(zend_execute_data *execute_data)
#define ZEND_OBSERVER_ENABLED
#define EXPECTED(condition)
#define zend_always_inline
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
ZEND_API zend_string * zend_string_concat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
#define Z_TRY_ADDREF_P(pz)
#define Z_ISUNDEF_P(zval_p)
#define ZVAL_STR_COPY(z, s)
struct _zend_array HashTable
#define ZVAL_COPY_DEREF(z, v)
#define IS_OBJ_DESTRUCTOR_CALLED
#define Z_OPLINE_NUM_P(zval_p)
#define ZVAL_NEW_STR(z, s)
#define ZVAL_OBJ_COPY(z, o)
ZEND_RESULT_CODE zend_result
struct _zend_object_handlers zend_object_handlers
struct _zend_execute_data zend_execute_data
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zend_generator * generator
#define ZEND_GENERATOR_CREATE
#define ZEND_HANDLE_EXCEPTION