Commit:    247bb737d552508829c5de7770ed0b15c3d8f7fd
Author:    Nikita Popov <ni...@php.net>         Sun, 27 May 2012 03:50:31 +0200
Parents:   39d3d5ec138119acf614fb285e92c3bcda7a2555
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=247bb737d552508829c5de7770ed0b15c3d8f7fd

Log:
Add support for generator methods

Changed paths:
  M  Zend/zend_generators.c
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h


Diff:
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 36a9727..ae706f1 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -48,6 +48,10 @@ void zend_generator_close(zend_generator *generator 
TSRMLS_DC) /* {{{ */
                        }
                }
 
+               if (execute_data->current_this) {
+                       zval_ptr_dtor(&execute_data->current_this);
+               }
+
                efree(execute_data);
                generator->execute_data = NULL;
        }
@@ -105,28 +109,43 @@ static void zend_generator_resume(zval *object, 
zend_generator *generator TSRMLS
                return;
        }
 
-       /* Backup executor globals */
-       zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
-       zend_op **original_opline_ptr = EG(opline_ptr);
-       zend_op_array *original_active_op_array = EG(active_op_array);
-
-       /* We (mis) use the return_value_ptr_ptr to provide the generator object
-        * to the executor. This way YIELD will be able to set the yielded 
value */
-       EG(return_value_ptr_ptr) = &object;
-
-       EG(opline_ptr) = &generator->execute_data->opline;
-       EG(active_op_array) = generator->execute_data->op_array;
-
-       /* Go to next opcode (we don't want to run the last one again) */
-       generator->execute_data->opline++;
-
-       /* Resume execution */
-       execute_ex(generator->execute_data TSRMLS_CC);
-
-       /* Restore executor globals */
-       EG(return_value_ptr_ptr) = original_return_value_ptr_ptr;
-       EG(opline_ptr) = original_opline_ptr;
-       EG(active_op_array) = original_active_op_array;
+       {
+               /* Backup executor globals */
+               zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
+               zend_op **original_opline_ptr = EG(opline_ptr);
+               zend_op_array *original_active_op_array = EG(active_op_array);
+               HashTable *original_active_symbol_table = 
EG(active_symbol_table);
+               zval *original_This = EG(This);
+               zend_class_entry *original_scope = EG(scope);
+               zend_class_entry *original_called_scope = EG(called_scope);
+
+               /* We (mis)use the return_value_ptr_ptr to provide the 
generator object
+                * to the executor, so YIELD will be able to set the yielded 
value */
+               EG(return_value_ptr_ptr) = &object;
+
+               /* Set executor globals */
+               EG(opline_ptr) = &generator->execute_data->opline;
+               EG(active_op_array) = generator->execute_data->op_array;
+               EG(active_symbol_table) = generator->execute_data->symbol_table;
+               EG(This) = generator->execute_data->current_this;
+               EG(scope) = generator->execute_data->current_scope;
+               EG(called_scope) = 
generator->execute_data->current_called_scope;
+
+               /* Go to next opcode (we don't want to run the last one again) 
*/
+               generator->execute_data->opline++;
+
+               /* Resume execution */
+               execute_ex(generator->execute_data TSRMLS_CC);
+
+               /* Restore executor globals */
+               EG(return_value_ptr_ptr) = original_return_value_ptr_ptr;
+               EG(opline_ptr) = original_opline_ptr;
+               EG(active_op_array) = original_active_op_array;
+               EG(active_symbol_table) = original_active_symbol_table;
+               EG(This) = original_This;
+               EG(scope) = original_scope;
+               EG(called_scope) = original_called_scope;
+       }
 }
 /* }}} */
 
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 781bd9f..42397ed 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -5225,6 +5225,11 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, 
ANY, ANY)
 
                *EG(return_value_ptr_ptr) = return_value;
 
+               /* back up some executor globals */
+               EX(current_this) = EG(This);
+               EX(current_scope) = EG(scope);
+               EX(current_called_scope) = EG(called_scope);
+
                /* back up the execution context */
                generator = (zend_generator *) 
zend_object_store_get_object(return_value TSRMLS_CC);
                generator->execute_data = execute_data;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 1eac105..fa802c6 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1207,6 +1207,11 @@ static int ZEND_FASTCALL  
ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP
 
                *EG(return_value_ptr_ptr) = return_value;
 
+               /* back up some executor globals */
+               EX(current_this) = EG(This);
+               EX(current_scope) = EG(scope);
+               EX(current_called_scope) = EG(called_scope);
+
                /* back up the execution context */
                generator = (zend_generator *) 
zend_object_store_get_object(return_value TSRMLS_CC);
                generator->execute_data = execute_data;


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to