Skip to content

Commit

Permalink
Close generator on return
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed May 26, 2012
1 parent 5bb3a99 commit d49d397
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 12 deletions.
19 changes: 16 additions & 3 deletions Zend/zend_generators.c
Expand Up @@ -26,10 +26,8 @@
ZEND_API zend_class_entry *zend_ce_generator;
static zend_object_handlers zend_generator_handlers;

static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* {{{ */
void zend_generator_close(zend_generator *generator TSRMLS_DC) /* {{{ */
{
zend_object_std_dtor(&generator->std TSRMLS_CC);

if (generator->execute_data) {
zend_execute_data *execute_data = generator->execute_data;

Expand All @@ -51,12 +49,22 @@ static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /*
}

efree(execute_data);
generator->execute_data = NULL;
}

if (generator->value) {
zval_ptr_dtor(&generator->value);
generator->value = NULL;
}

}
/* }}} */

static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* {{{ */
{
zend_generator_close(generator TSRMLS_CC);

zend_object_std_dtor(&generator->std TSRMLS_CC);
efree(generator);
}
/* }}} */
Expand Down Expand Up @@ -92,6 +100,11 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /*

static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS_DC) /* {{{ */
{
/* The generator is already closed, thus can't resume */
if (!generator->execute_data) {
return;
}

/* Backup executor globals */
zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
zend_op **original_opline_ptr = EG(opline_ptr);
Expand Down
9 changes: 5 additions & 4 deletions Zend/zend_generators.h
Expand Up @@ -23,10 +23,6 @@

BEGIN_EXTERN_C()

void zend_register_generator_ce(TSRMLS_D);

extern ZEND_API zend_class_entry *zend_ce_generator;

typedef struct _zend_generator {
zend_object std;

Expand All @@ -36,6 +32,11 @@ typedef struct _zend_generator {
zval *value;
} zend_generator;

extern ZEND_API zend_class_entry *zend_ce_generator;

void zend_register_generator_ce(TSRMLS_D);
void zend_generator_close(zend_generator *generator TSRMLS_DC);

END_EXTERN_C()

#endif
Expand Down
8 changes: 7 additions & 1 deletion Zend/zend_vm_def.h
Expand Up @@ -2840,8 +2840,14 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
zval *retval_ptr;
zend_free_op free_op1;

/* For generators return means to simply stop executing */
if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC);

/* Close the generator to free up resources. */
zend_generator_close(generator TSRMLS_CC);

/* Pass execution back to generator handling code */
ZEND_VM_RETURN();
}

Expand Down
32 changes: 28 additions & 4 deletions Zend/zend_vm_execute.h
Expand Up @@ -2321,8 +2321,14 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
zval *retval_ptr;


/* For generators return means to simply stop executing */
if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC);

/* Close the generator to free up resources. */
zend_generator_close(generator TSRMLS_CC);

/* Pass execution back to generator handling code */
ZEND_VM_RETURN();
}

Expand Down Expand Up @@ -6899,8 +6905,14 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *retval_ptr;
zend_free_op free_op1;

/* For generators return means to simply stop executing */
if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC);

/* Close the generator to free up resources. */
zend_generator_close(generator TSRMLS_CC);

/* Pass execution back to generator handling code */
ZEND_VM_RETURN();
}

Expand Down Expand Up @@ -11382,8 +11394,14 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *retval_ptr;
zend_free_op free_op1;

/* For generators return means to simply stop executing */
if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC);

/* Close the generator to free up resources. */
zend_generator_close(generator TSRMLS_CC);

/* Pass execution back to generator handling code */
ZEND_VM_RETURN();
}

Expand Down Expand Up @@ -27421,8 +27439,14 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *retval_ptr;


/* For generators return means to simply stop executing */
if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC);

/* Close the generator to free up resources. */
zend_generator_close(generator TSRMLS_CC);

/* Pass execution back to generator handling code */
ZEND_VM_RETURN();
}

Expand Down

0 comments on commit d49d397

Please sign in to comment.