Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add support for yielding keys

Keys are yielded using the

    yield $key => $value

syntax. Currently this is implemented as a statement only and not as an
expression, because conflicts arise considering nesting and use in arrays:

    yield yield $a => $b;
    // could be either
    yield (yield $a) => $b;
    // or
    yield (yield $a => $b);

Once I find some way to resolve these conflicts this should be available
as an expression too.

Also the key yielding code is rather copy-and-past-y for the value yielding
code, so that should be factored out.
  • Loading branch information...
commit bc08c2cf9485e20fea0eef7ab149cefdf9a3662e 1 parent 72a91d0
@nikic nikic authored
View
26 Zend/tests/generators/generator_with_keys.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Generators can also yield keys
+--FILE--
+<?php
+
+function *reverse(array $array) {
+ end($array);
+ while (null !== $key = key($array)) {
+ yield $key => current($array);
+ prev($array);
+ }
+}
+
+$array = [
+ 'foo' => 'bar',
+ 'bar' => 'foo',
+];
+
+foreach (reverse($array) as $key => $value) {
+ echo $key, ' => ', $value, "\n";
+}
+
+?>
+--EXPECT--
+bar => foo
+foo => bar
View
12 Zend/zend_compile.c
@@ -2662,7 +2662,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
}
/* }}} */
-void zend_do_yield(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
+void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC) /* {{{ */
{
zend_op *opline;
@@ -2674,8 +2674,14 @@ void zend_do_yield(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
opline->opcode = ZEND_YIELD;
- if (expr) {
- SET_NODE(opline->op1, expr);
+ if (value) {
+ SET_NODE(opline->op1, value);
+ } else {
+ SET_UNUSED(opline->op1);
+ }
+
+ if (key) {
+ SET_NODE(opline->op2, key);
} else {
SET_UNUSED(opline->op2);
}
View
2  Zend/zend_compile.h
@@ -490,7 +490,7 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c
int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC);
void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
-void zend_do_yield(znode *result, const znode *expr TSRMLS_DC);
+void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC);
void zend_do_suspend_if_generator(TSRMLS_D);
void zend_do_handle_exception(TSRMLS_D);
View
8 Zend/zend_generators.c
@@ -92,6 +92,10 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio
generator->value = NULL;
}
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ generator->key = NULL;
+ }
}
/* }}} */
@@ -269,6 +273,10 @@ ZEND_METHOD(Generator, key)
generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC);
zend_generator_ensure_initialized(object, generator TSRMLS_CC);
+
+ if (generator->key) {
+ RETURN_ZVAL(generator->key, 1, 0);
+ }
}
/* }}} */
View
2  Zend/zend_generators.h
@@ -30,6 +30,8 @@ typedef struct _zend_generator {
zend_execute_data *execute_data;
/* Current value */
zval *value;
+ /* Current key */
+ zval *key;
/* Variable to put sent value into */
temp_variable *send_target;
} zend_generator;
View
5 Zend/zend_language_parser.y
@@ -299,6 +299,7 @@ unticked_statement:
| T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); }
| T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); }
| T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); }
+ | T_YIELD expr T_DOUBLE_ARROW expr ';' { zend_do_yield(&$$, &$4, &$2 TSRMLS_CC); }
| T_GLOBAL global_var_list ';'
| T_STATIC static_var_list ';'
| T_ECHO echo_expr_list ';'
@@ -801,8 +802,8 @@ expr_without_variable:
| combined_scalar { $$ = $1; }
| '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
| T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
- | T_YIELD { zend_do_yield(&$$, NULL TSRMLS_CC); }
- | T_YIELD expr { zend_do_yield(&$$, &$2 TSRMLS_CC); }
+ | T_YIELD { zend_do_yield(&$$, NULL, NULL TSRMLS_CC); }
+ | T_YIELD expr { zend_do_yield(&$$, &$2, NULL TSRMLS_CC); }
| function is_generator is_reference { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, $3.op_type, 0 TSRMLS_CC); }
'(' parameter_list ')' lexical_vars { zend_do_suspend_if_generator(TSRMLS_C); }
'{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
View
41 Zend/zend_vm_def.h
@@ -5258,7 +5258,7 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY)
ZEND_VM_RETURN();
}
-ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, ANY)
+ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSED)
{
USE_OPLINE
@@ -5270,6 +5270,11 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, ANY)
zval_ptr_dtor(&generator->value);
}
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
/* Set the new yielded value */
if (OP1_TYPE != IS_UNUSED) {
zend_free_op free_op1;
@@ -5297,11 +5302,43 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, ANY)
FREE_OP1_IF_VAR();
} else {
- /* If no value way specified yield null */
+ /* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
generator->value = &EG(uninitialized_zval);
}
+ /* Set the new yielded key */
+ if (OP2_TYPE != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = GET_OP2_ZVAL_PTR(BP_VAR_R);
+
+ /* Consts, temporary variables and references need copying */
+ if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!IS_OP1_TMP_FREE()) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ FREE_OP2_IF_VAR();
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
/* If a value is sent it should go into the result var */
generator->send_target = &EX_T(opline->result.var);
View
2,671 Zend/zend_vm_execute.h
@@ -3034,63 +3034,6 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- /* 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);
-
- /* Destroy the previously yielded value */
- if (generator->value) {
- zval_ptr_dtor(&generator->value);
- }
-
- /* Set the new yielded value */
- if (IS_CONST != IS_UNUSED) {
-
- zval *value = opline->op1.zv;
-
- /* Consts, temporary variables and references need copying */
- if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
-
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
-
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
-
- generator->value = copy;
- } else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
-
- } else {
- /* If no value way specified yield null */
- Z_ADDREF(EG(uninitialized_zval));
- generator->value = &EG(uninitialized_zval);
- }
-
- /* If a value is sent it should go into the result var */
- generator->send_target = &EX_T(opline->result.var);
-
- /* Initialize the sent value to NULL */
- Z_ADDREF(EG(uninitialized_zval));
- AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
-
- /* The GOTO VM uses a local opline variable. We need to set the opline
- * variable in execute_data so we don't resume at an old position. */
- SAVE_OPLINE();
-
- ZEND_VM_RETURN();
-}
-
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -4111,6 +4054,99 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *key = opline->op2.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -4651,6 +4687,99 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN
}
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -5516,6 +5645,100 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -6075,6 +6298,99 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *key = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -6674,6 +6990,99 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND
}
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CV != IS_UNUSED) {
+
+ zval *key = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -7688,63 +8097,6 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- /* 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);
-
- /* Destroy the previously yielded value */
- if (generator->value) {
- zval_ptr_dtor(&generator->value);
- }
-
- /* Set the new yielded value */
- if (IS_TMP_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
-
- /* Consts, temporary variables and references need copying */
- if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
-
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
-
- /* Temporary variables don't need ctor copying */
- if (!1) {
- zval_copy_ctor(copy);
- }
-
- generator->value = copy;
- } else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
-
- } else {
- /* If no value way specified yield null */
- Z_ADDREF(EG(uninitialized_zval));
- generator->value = &EG(uninitialized_zval);
- }
-
- /* If a value is sent it should go into the result var */
- generator->send_target = &EX_T(opline->result.var);
-
- /* Initialize the sent value to NULL */
- Z_ADDREF(EG(uninitialized_zval));
- AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
-
- /* The GOTO VM uses a local opline variable. We need to set the opline
- * variable in execute_data so we don't resume at an old position. */
- SAVE_OPLINE();
-
- ZEND_VM_RETURN();
-}
-
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -8633,6 +8985,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *key = opline->op2.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -9173,6 +9618,99 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL
}
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -10038,6 +10576,100 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -10463,6 +11095,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *key = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -11000,6 +11725,99 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE
}
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CV != IS_UNUSED) {
+
+ zval *key = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -12419,64 +13237,6 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- /* 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);
-
- /* Destroy the previously yielded value */
- if (generator->value) {
- zval_ptr_dtor(&generator->value);
- }
-
- /* Set the new yielded value */
- if (IS_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
-
- /* Consts, temporary variables and references need copying */
- if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
-
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
-
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
-
- generator->value = copy;
- } else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
-
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- /* If no value way specified yield null */
- Z_ADDREF(EG(uninitialized_zval));
- generator->value = &EG(uninitialized_zval);
- }
-
- /* If a value is sent it should go into the result var */
- generator->send_target = &EX_T(opline->result.var);
-
- /* Initialize the sent value to NULL */
- Z_ADDREF(EG(uninitialized_zval));
- AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
-
- /* The GOTO VM uses a local opline variable. We need to set the opline
- * variable in execute_data so we don't resume at an old position. */
- SAVE_OPLINE();
-
- ZEND_VM_RETURN();
-}
-
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -14816,6 +15576,100 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN
return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *key = opline->op2.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -16742,6 +17596,100 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_
return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -19048,6 +19996,101 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_
return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -20032,6 +21075,100 @@ static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *key = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -22007,6 +23144,100 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER(ZEND_O
return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op1;
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CV != IS_UNUSED) {
+
+ zval *key = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -22092,63 +23323,6 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
-static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- /* 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);
-
- /* Destroy the previously yielded value */
- if (generator->value) {
- zval_ptr_dtor(&generator->value);
- }
-
- /* Set the new yielded value */
- if (IS_UNUSED != IS_UNUSED) {
-
- zval *value = NULL;
-
- /* Consts, temporary variables and references need copying */
- if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
-
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
-
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
-
- generator->value = copy;
- } else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
-
- } else {
- /* If no value way specified yield null */
- Z_ADDREF(EG(uninitialized_zval));
- generator->value = &EG(uninitialized_zval);
- }
-
- /* If a value is sent it should go into the result var */
- generator->send_target = &EX_T(opline->result.var);
-
- /* Initialize the sent value to NULL */
- Z_ADDREF(EG(uninitialized_zval));
- AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
-
- /* The GOTO VM uses a local opline variable. We need to set the opline
- * variable in execute_data so we don't resume at an old position. */
- SAVE_OPLINE();
-
- ZEND_VM_RETURN();
-}
-
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -23398,6 +24572,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(
return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *key = opline->op2.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -24556,6 +25823,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE
return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -25714,6 +27074,100 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER(ZE
return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *key = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -25983,6 +27437,99 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE
}
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *key = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -27138,6 +28685,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEN
return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CV != IS_UNUSED) {
+
+ zval *key = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -28379,63 +30019,6 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- /* 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);
-
- /* Destroy the previously yielded value */
- if (generator->value) {
- zval_ptr_dtor(&generator->value);
- }
-
- /* Set the new yielded value */
- if (IS_CV != IS_UNUSED) {
-
- zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
-
- /* Consts, temporary variables and references need copying */
- if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
-
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
-
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
-
- generator->value = copy;
- } else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
-
- } else {
- /* If no value way specified yield null */
- Z_ADDREF(EG(uninitialized_zval));
- generator->value = &EG(uninitialized_zval);
- }
-
- /* If a value is sent it should go into the result var */
- generator->send_target = &EX_T(opline->result.var);
-
- /* Initialize the sent value to NULL */
- Z_ADDREF(EG(uninitialized_zval));
- AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
-
- /* The GOTO VM uses a local opline variable. We need to set the opline
- * variable in execute_data so we don't resume at an old position. */
- SAVE_OPLINE();
-
- ZEND_VM_RETURN();
-}
-
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -30554,6 +32137,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND
return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ /* 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);
+
+ /* Destroy the previously yielded value */
+ if (generator->value) {
+ zval_ptr_dtor(&generator->value);
+ }
+
+ /* Destroy the previously yielded key */
+ if (generator->key) {
+ zval_ptr_dtor(&generator->key);
+ }
+
+ /* Set the new yielded value */
+ if (IS_CV != IS_UNUSED) {
+
+ zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ } else {
+ /* If no value was specified yield null */
+ Z_ADDREF(EG(uninitialized_zval));
+ generator->value = &EG(uninitialized_zval);
+ }
+
+ /* Set the new yielded key */
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *key = opline->op2.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, key);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->key = copy;
+ } else {
+ Z_ADDREF_P(key);
+ generator->key = key;
+ }
+
+ } else {
+ /* Setting the key to NULL signals that the auto-increment key
+ * generation should be used */
+ generator->key = NULL;
+ }
+
+ /* If a value is sent it should go into the result var */
+ generator->send_target = &EX_T(opline->result.var);
+
+ /* Initialize the sent value to NULL */
+ Z_ADDREF(EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ /* The GOTO VM uses a local opline variable. We need to set the opline
+ * variable in execute_data so we don't resume at an old position. */
+ SAVE_OPLINE();
+
+ ZEND_VM_RETURN();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -32351,6 +34027,99 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_O
return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);