Skip to content

Commit

Permalink
Add support for generator methods
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed May 27, 2012
1 parent 39d3d5e commit 247bb73
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 22 deletions.
63 changes: 41 additions & 22 deletions Zend/zend_generators.c
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
}
/* }}} */

Expand Down
5 changes: 5 additions & 0 deletions Zend/zend_vm_def.h
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions Zend/zend_vm_execute.h
Expand Up @@ -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;
Expand Down

0 comments on commit 247bb73

Please sign in to comment.