Permalink
Browse files

Close generator on return

  • Loading branch information...
1 parent 5bb3a99 commit d49d3971e630121a3cc11196b88f7afa2b1e2f26 @nikic nikic committed May 26, 2012
Showing with 56 additions and 12 deletions.
  1. +16 −3 Zend/zend_generators.c
  2. +5 −4 Zend/zend_generators.h
  3. +7 −1 Zend/zend_vm_def.h
  4. +28 −4 Zend/zend_vm_execute.h
@@ -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;
@@ -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);
}
/* }}} */
@@ -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);
@@ -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;
@@ -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
View
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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();
}

0 comments on commit d49d397

Please sign in to comment.