1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Implement Generator::getReturn()

This commit is contained in:
Nikita Popov
2015-02-19 20:17:37 +01:00
parent d428bf2d4e
commit 79f26e9ca5
11 changed files with 526 additions and 75 deletions

View File

@@ -1,13 +0,0 @@
--TEST--
Generators cannot return values (even before yield)
--FILE--
<?php
function gen() {
return $foo;
yield;
}
?>
--EXPECTF--
Fatal error: Generators cannot return values using "return" in %s on line 4

View File

@@ -1,13 +0,0 @@
--TEST--
Generators cannot return values
--FILE--
<?php
function gen() {
yield;
return $abc;
}
?>
--EXPECTF--
Fatal error: Generators cannot return values using "return" in %s on line 5

View File

@@ -0,0 +1,81 @@
--TEST--
Generator::getReturn() success cases
--FILE--
<?php
function gen1() {
return 42;
yield 24;
}
$gen = gen1();
// Calling getReturn() directly here is okay due to auto-priming
var_dump($gen->getReturn());
function gen2() {
yield 24;
return 42;
}
$gen = gen2();
var_dump($gen->current());
$gen->next();
var_dump($gen->getReturn());
// & for generators specifies by-reference yield, not return
// so it's okay to return a literal
function &gen3() {
$var = 24;
yield $var;
return 42;
}
$gen = gen3();
var_dump($gen->current());
$gen->next();
var_dump($gen->getReturn());
// Return types for generators specify the return of the function,
// not of the generator return value, so this code is okay
function gen4() : Generator {
yield 24;
return 42;
}
$gen = gen4();
var_dump($gen->current());
$gen->next();
var_dump($gen->getReturn());
// Has no explicit return, but implicitly return NULL at the end
function gen5() {
yield 24;
}
$gen = gen5();
var_dump($gen->current());
$gen->next();
var_dump($gen->getReturn());
// Explicit value-less return also results in a NULL generator
// return value and there is no interference with type hints
function gen6() : Generator {
return;
yield 24;
}
$gen = gen6();
var_dump($gen->getReturn());
?>
--EXPECTF--
int(42)
int(24)
int(42)
int(24)
int(42)
int(24)
int(42)
int(24)
NULL
NULL

View File

@@ -0,0 +1,47 @@
--TEST--
Test interaction of Generator::getReturn() and finally
--FILE--
<?php
function gen1() {
try {
throw new Exception("gen1() throw");
} finally {
return 42;
}
yield;
}
// The exception was discarded, so this works
$gen = gen1();
var_dump($gen->getReturn());
function gen2() {
try {
return 42;
} finally {
throw new Exception("gen2() throw");
}
yield;
}
$gen = gen2();
try {
// This will throw an exception (from the finally)
// during auto-priming, so fails
var_dump($gen->getReturn());
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
try {
// This fails, because the return value was discarded
var_dump($gen->getReturn());
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
int(42)
gen2() throw
Cannot get return value of a generator that hasn't returned

View File

@@ -0,0 +1,79 @@
--TEST--
Generator::getReturn() error cases
--FILE--
<?php
function gen1() {
yield 1;
yield 2;
return 3;
}
$gen = gen1();
try {
// Generator hasn't reached the "return" yet
$gen->getReturn();
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
function gen2() {
throw new Exception("gen2() throw");
yield 1;
return 2;
}
$gen = gen2();
try {
$gen->next();
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
try {
// Generator has been aborted as a result of an exception
$gen->getReturn();
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
function gen3() {
throw new Exception("gen3() throw");
return 1;
yield 2;
}
$gen = gen3();
try {
// Generator throws during auto-priming of getReturn() call
$gen->getReturn();
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
function gen4() {
yield;
return 1;
}
$gen = gen4();
try {
$gen->throw(new Exception("gen4() throw"));
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
try {
// Generator has been aborted as a result of an exception
// that was injected using throw()
$gen->getReturn();
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Cannot get return value of a generator that hasn't returned
gen2() throw
Cannot get return value of a generator that hasn't returned
gen3() throw
gen4() throw
Cannot get return value of a generator that hasn't returned

View File

@@ -0,0 +1,59 @@
--TEST--
Test different types of generator return values (VM operands)
--FILE--
<?php
function gen1() {
return; // CONST
yield;
}
$gen = gen1();
var_dump($gen->getReturn());
function gen2() {
return "str"; // CONST
yield;
}
$gen = gen2();
var_dump($gen->getReturn());
function gen3($var) {
return $var; // CV
yield;
}
$gen = gen3([1, 2, 3]);
var_dump($gen->getReturn());
function gen4($obj) {
return $obj->prop; // VAR
yield;
}
$gen = gen4((object) ['prop' => 321]);
var_dump($gen->getReturn());
function gen5($val) {
return (int) $val; // TMP
yield;
}
$gen = gen5("42");
var_dump($gen->getReturn());
?>
--EXPECT--
NULL
string(3) "str"
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
int(321)
int(42)

View File

@@ -186,6 +186,10 @@ static void zend_generator_free_storage(zend_object *object) /* {{{ */
zend_generator_close(generator, 0);
if (!Z_ISUNDEF(generator->retval)) {
zval_ptr_dtor(&generator->retval);
}
zend_object_std_dtor(&generator->std);
if (generator->iterator) {
@@ -204,6 +208,8 @@ static zend_object *zend_generator_create(zend_class_entry *class_type) /* {{{ *
/* The key will be incremented on first use, so it'll start at 0 */
generator->largest_used_integer_key = -1;
ZVAL_UNDEF(&generator->retval);
zend_object_std_init(&generator->std, class_type);
generator->std.handlers = &zend_generator_handlers;
@@ -535,6 +541,34 @@ ZEND_METHOD(Generator, throw)
}
/* }}} */
/* {{{ proto mixed Generator::getReturn()
* Retrieves the return value of the generator */
ZEND_METHOD(Generator, getReturn)
{
zend_generator *generator;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
generator = (zend_generator *) Z_OBJ_P(getThis());
zend_generator_ensure_initialized(generator);
if (EG(exception)) {
return;
}
if (Z_ISUNDEF(generator->retval)) {
/* Generator hasn't returned yet -> error! */
zend_throw_exception(NULL,
"Cannot get return value of a generator that hasn't returned", 0);
return;
}
ZVAL_COPY(return_value, &generator->retval);
}
/* }}} */
/* {{{ proto void Generator::__wakeup()
* Throws an Exception as generators can't be serialized */
ZEND_METHOD(Generator, __wakeup)
@@ -668,6 +702,7 @@ static const zend_function_entry generator_functions[] = {
ZEND_ME(Generator, next, arginfo_generator_void, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, send, arginfo_generator_send, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, throw, arginfo_generator_throw, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, getReturn,arginfo_generator_void, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, __wakeup, arginfo_generator_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};

View File

@@ -40,6 +40,8 @@ typedef struct _zend_generator {
zval value;
/* Current key */
zval key;
/* Return value */
zval retval;
/* Variable to put sent value into */
zval *send_target;
/* Largest used integer key for auto-incrementing keys */

View File

@@ -780,11 +780,6 @@ ZEND_API int pass_two(zend_op_array *op_array)
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
if (opline->op1_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(op_array, opline->op1)) != IS_NULL) {
CG(zend_lineno) = opline->lineno;
zend_error_noreturn(E_COMPILE_ERROR, "Generators cannot return values using \"return\"");
}
opline->opcode = ZEND_GENERATOR_RETURN;
}
break;

View File

@@ -3076,11 +3076,36 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY)
ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
zval *retval;
zend_free_op free_op1;
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
SAVE_OPLINE();
retval = GET_OP1_ZVAL_PTR(BP_VAR_R);
/* Copy return value into generator->retval */
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (OP1_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) {
zval_copy_ctor_func(&generator->retval);
}
}
} else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_ISREF_P(retval)) {
ZVAL_COPY(&generator->retval, Z_REFVAL_P(retval));
FREE_OP1_IF_VAR();
} else {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (OP1_TYPE == IS_CV) {
if (Z_OPT_REFCOUNTED_P(retval)) Z_ADDREF_P(retval);
}
}
/* Close the generator to free up resources */
zend_generator_close(generator, 1);
@@ -6085,7 +6110,10 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
@@ -6116,7 +6144,10 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
ZEND_VM_CONTINUE();
case ZEND_USER_OPCODE_RETURN:
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
@@ -6400,7 +6431,10 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}

View File

@@ -675,18 +675,6 @@ fcall_end:
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
/* Close the generator to free up resources */
zend_generator_close(generator, 1);
/* Pass execution back to handling code */
ZEND_VM_RETURN();
}
static int ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -1396,7 +1384,10 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
@@ -1427,7 +1418,10 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZEND_VM_CONTINUE();
case ZEND_USER_OPCODE_RETURN:
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
@@ -1502,7 +1496,10 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
@@ -2608,6 +2605,43 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *retval;
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
SAVE_OPLINE();
retval = EX_CONSTANT(opline->op1);
/* Copy return value into generator->retval */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_CONST == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) {
zval_copy_ctor_func(&generator->retval);
}
}
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(retval)) {
ZVAL_COPY(&generator->retval, Z_REFVAL_P(retval));
} else {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_CONST == IS_CV) {
if (Z_OPT_REFCOUNTED_P(retval)) Z_ADDREF_P(retval);
}
}
/* Close the generator to free up resources */
zend_generator_close(generator, 1);
/* Pass execution back to handling code */
ZEND_VM_RETURN();
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -8878,6 +8912,43 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *retval;
zend_free_op free_op1;
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
SAVE_OPLINE();
retval = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
/* Copy return value into generator->retval */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_TMP_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) {
zval_copy_ctor_func(&generator->retval);
}
}
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(retval)) {
ZVAL_COPY(&generator->retval, Z_REFVAL_P(retval));
} else {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_TMP_VAR == IS_CV) {
if (Z_OPT_REFCOUNTED_P(retval)) Z_ADDREF_P(retval);
}
}
/* Close the generator to free up resources */
zend_generator_close(generator, 1);
/* Pass execution back to handling code */
ZEND_VM_RETURN();
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -11555,6 +11626,43 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *retval;
zend_free_op free_op1;
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
SAVE_OPLINE();
retval = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
/* Copy return value into generator->retval */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) {
zval_copy_ctor_func(&generator->retval);
}
}
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(retval)) {
ZVAL_COPY(&generator->retval, Z_REFVAL_P(retval));
zval_ptr_dtor_nogc(free_op1);
} else {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_VAR == IS_CV) {
if (Z_OPT_REFCOUNTED_P(retval)) Z_ADDREF_P(retval);
}
}
/* Close the generator to free up resources */
zend_generator_close(generator, 1);
/* Pass execution back to handling code */
ZEND_VM_RETURN();
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -23874,6 +23982,43 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *retval;
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
SAVE_OPLINE();
retval = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
/* Copy return value into generator->retval */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_CV == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) {
zval_copy_ctor_func(&generator->retval);
}
}
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(retval)) {
ZVAL_COPY(&generator->retval, Z_REFVAL_P(retval));
} else {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (IS_CV == IS_CV) {
if (Z_OPT_REFCOUNTED_P(retval)) Z_ADDREF_P(retval);
}
}
/* Close the generator to free up resources */
zend_generator_close(generator, 1);
/* Pass execution back to handling code */
ZEND_VM_RETURN();
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -40838,31 +40983,31 @@ void zend_init_opcodes_handlers(void)
ZEND_YIELD_SPEC_CV_VAR_HANDLER,
ZEND_YIELD_SPEC_CV_UNUSED_HANDLER,
ZEND_YIELD_SPEC_CV_CV_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,