From: Nikita Popov Date: Mon, 25 Mar 2013 16:40:58 +0000 (+0100) Subject: Remove support for cloning generators X-Git-Tag: php-5.5.0beta3~8^2~49^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8345abcabb487c128ac5ee29884e0ae7d705bd47;p=php Remove support for cloning generators --- diff --git a/Zend/tests/generators/clone.phpt b/Zend/tests/generators/clone.phpt index 36811dfe6e..22f4428121 100644 --- a/Zend/tests/generators/clone.phpt +++ b/Zend/tests/generators/clone.phpt @@ -1,32 +1,15 @@ --TEST-- -Generators can be cloned +Generators cannot be cloned --FILE-- current()); -$g1->next(); - -$g2 = clone $g1; -var_dump($g2->current()); -$g2->next(); - -var_dump($g2->current()); -var_dump($g1->current()); - -$g1->next(); -var_dump($g1->current()); +$gen = gen(); +clone $gen; ?> ---EXPECT-- -int(0) -int(1) -int(2) -int(1) -int(2) +--EXPECTF-- +Fatal error: Trying to clone an uncloneable object of class Generator in %s on line %d diff --git a/Zend/tests/generators/clone_after_object_call.phpt b/Zend/tests/generators/clone_after_object_call.phpt deleted file mode 100644 index 0a424268cc..0000000000 --- a/Zend/tests/generators/clone_after_object_call.phpt +++ /dev/null @@ -1,20 +0,0 @@ ---TEST-- -Cloning a generator after an object method was called ---FILE-- -b(); - yield; -} - -$g1 = gen(); -$g1->rewind(); -$g2 = clone $g1; - -echo "Done"; ---EXPECT-- -Done diff --git a/Zend/tests/generators/clone_with_foreach.phpt b/Zend/tests/generators/clone_with_foreach.phpt deleted file mode 100644 index b05ed07312..0000000000 --- a/Zend/tests/generators/clone_with_foreach.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Cloning a generator with a foreach loop properly adds a ref for the loop var ---FILE-- -current()); - -$g2 = clone $g1; -var_dump($g2->current()); - -$g1->next(); -$g2->next(); -var_dump($g1->current()); -var_dump($g2->current()); - -unset($g1); -$g2->next(); -var_dump($g2->current()); - -?> ---EXPECT-- -int(1) -int(1) -int(2) -int(2) -int(3) diff --git a/Zend/tests/generators/clone_with_properties.phpt b/Zend/tests/generators/clone_with_properties.phpt deleted file mode 100644 index 900253c682..0000000000 --- a/Zend/tests/generators/clone_with_properties.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Tests cloning a generator with properties ---FILE-- -prop = 'val'; - -$g2 = clone $g1; -unset($g1); - -var_dump($g2->prop); - -?> ---EXPECT-- -string(3) "val" diff --git a/Zend/tests/generators/clone_with_stack.phpt b/Zend/tests/generators/clone_with_stack.phpt deleted file mode 100644 index 5a8e6d842c..0000000000 --- a/Zend/tests/generators/clone_with_stack.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -A generator with an active stack can be cloned ---FILE-- -rewind(); -$g2 = clone $g1; -unset($g1); -$g2->send(10); - -?> ---EXPECT-- -string(10) "xxxxxxxxxx" diff --git a/Zend/tests/generators/clone_with_symbol_table.phpt b/Zend/tests/generators/clone_with_symbol_table.phpt deleted file mode 100644 index e1fefebd8f..0000000000 --- a/Zend/tests/generators/clone_with_symbol_table.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -A generator using a symbol table can be cloned ---FILE-- - 'bar']); - - // interrupt - yield; - - var_dump($foo); -} - -$g1 = gen(); -$g1->rewind(); -$g2 = clone $g1; -unset($g1); -$g2->next(); - -?> ---EXPECT-- -string(3) "bar" diff --git a/Zend/tests/generators/clone_with_this.phpt b/Zend/tests/generators/clone_with_this.phpt deleted file mode 100644 index b242d851eb..0000000000 --- a/Zend/tests/generators/clone_with_this.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Cloning a generator method (with $this) ---FILE-- -foo = 'bar'; - yield; // interrupt - var_dump($this->foo); - } -} - -$g1 = (new Test)->gen(); -$g1->rewind(); // goto yield -$g2 = clone $g1; -unset($g1); -$g2->next(); - -?> ---EXPECT-- -string(3) "bar" diff --git a/Zend/tests/generators/nested_method_calls.phpt b/Zend/tests/generators/nested_method_calls.phpt index 98aee2e60b..0d640b31c6 100644 --- a/Zend/tests/generators/nested_method_calls.phpt +++ b/Zend/tests/generators/nested_method_calls.phpt @@ -26,10 +26,7 @@ $g2 = gen(new B); $g2->current(); $g1->next(); - -$g3 = clone $g2; -unset($g2); -$g3->next(); +$g2->next(); ?> --EXPECT-- diff --git a/Zend/tests/generators/yield_during_method_call.phpt b/Zend/tests/generators/yield_during_method_call.phpt index 5fbe84fff5..3a9914d58b 100644 --- a/Zend/tests/generators/yield_during_method_call.phpt +++ b/Zend/tests/generators/yield_during_method_call.phpt @@ -22,14 +22,6 @@ $gen = gen(); $gen->rewind(); unset($gen); -// test cloning -$g1 = gen(); -$g1->rewind(); -$g2 = clone $g1; -unset($g1); -$g2->send('bar'); - ?> --EXPECT-- foo -bar diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 3f43552f1f..d189148f47 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -196,175 +196,6 @@ static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* } /* }}} */ -static zend_object_value zend_generator_clone(zval *object TSRMLS_DC) /* {{{ */ -{ - zend_generator *orig = zend_object_store_get_object(object TSRMLS_CC); - zend_object_value clone_val = zend_generator_create(Z_OBJCE_P(object) TSRMLS_CC); - zend_generator *clone = zend_object_store_get_object_by_handle(clone_val.handle TSRMLS_CC); - - zend_objects_clone_members( - &clone->std, clone_val, &orig->std, Z_OBJ_HANDLE_P(object) TSRMLS_CC - ); - - clone->execute_data = orig->execute_data; - clone->largest_used_integer_key = orig->largest_used_integer_key; - clone->flags = orig->flags; - - if (orig->execute_data) { - /* Create a few shorter aliases to the old execution data */ - zend_execute_data *execute_data = orig->execute_data; - zend_op_array *op_array = execute_data->op_array; - HashTable *symbol_table = execute_data->symbol_table; - zend_execute_data *current_execute_data; - zend_op **opline_ptr; - HashTable *current_symbol_table; - zend_vm_stack current_stack; - zval *current_this; - void **stack_frame, **orig_stack_frame; - - /* Create new execution context. We have to back up and restore - * EG(current_execute_data), EG(opline_ptr), EG(active_symbol_table) - * and EG(This) here because the function modifies or uses them */ - current_execute_data = EG(current_execute_data); - EG(current_execute_data) = execute_data->prev_execute_data; - opline_ptr = EG(opline_ptr); - current_symbol_table = EG(active_symbol_table); - EG(active_symbol_table) = execute_data->symbol_table; - current_this = EG(This); - EG(This) = NULL; - current_stack = EG(argument_stack); - clone->execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC); - clone->stack = EG(argument_stack); - EG(argument_stack) = current_stack; - EG(This) = current_this; - EG(active_symbol_table) = current_symbol_table; - EG(current_execute_data) = current_execute_data; - EG(opline_ptr) = opline_ptr; - - /* copy */ - clone->execute_data->opline = execute_data->opline; - clone->execute_data->function_state = execute_data->function_state; - clone->execute_data->object = execute_data->object; - clone->execute_data->current_scope = execute_data->current_scope; - clone->execute_data->current_called_scope = execute_data->current_called_scope; - clone->execute_data->fast_ret = execute_data->fast_ret; - - if (!symbol_table) { - int i; - - /* Copy compiled variables */ - for (i = 0; i < op_array->last_var; i++) { - if (*EX_CV_NUM(execute_data, i)) { - *EX_CV_NUM(clone->execute_data, i) = (zval **) EX_CV_NUM(clone->execute_data, op_array->last_var + i); - **EX_CV_NUM(clone->execute_data, i) = *(zval **) EX_CV_NUM(execute_data, op_array->last_var + i); - Z_ADDREF_PP(*EX_CV_NUM(clone->execute_data, i)); - } - } - } else { - /* Copy symbol table */ - ALLOC_HASHTABLE(clone->execute_data->symbol_table); - zend_hash_init(clone->execute_data->symbol_table, zend_hash_num_elements(symbol_table), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(clone->execute_data->symbol_table, symbol_table, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); - - /* Update zval** pointers for compiled variables */ - { - int i; - for (i = 0; i < op_array->last_var; i++) { - if (zend_hash_quick_find(clone->execute_data->symbol_table, op_array->vars[i].name, op_array->vars[i].name_len + 1, op_array->vars[i].hash_value, (void **) EX_CV_NUM(clone->execute_data, i)) == FAILURE) { - *EX_CV_NUM(clone->execute_data, i) = NULL; - } - } - } - } - - /* Copy nested-calls stack */ - if (execute_data->call) { - clone->execute_data->call = clone->execute_data->call_slots + - (execute_data->call - execute_data->call_slots); - } else { - clone->execute_data->call = NULL; - } - memcpy(clone->execute_data->call_slots, execute_data->call_slots, ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls); - if (clone->execute_data->call >= clone->execute_data->call_slots) { - call_slot *call = clone->execute_data->call; - - while (call >= clone->execute_data->call_slots) { - if (call->object) { - Z_ADDREF_P(call->object); - } - call--; - } - } - - /* Copy the temporary variables */ - memcpy(EX_TMP_VAR_NUM(clone->execute_data, op_array->T-1), EX_TMP_VAR_NUM(execute_data, op_array->T-1), ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T); - - /* Copy arguments passed on stack */ - stack_frame = zend_vm_stack_frame_base(clone->execute_data); - orig_stack_frame = zend_vm_stack_frame_base(execute_data); - clone->stack->top = stack_frame + (orig->stack->top - orig_stack_frame); - if (clone->stack->top != stack_frame) { - memcpy(stack_frame, orig_stack_frame, ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (orig->stack->top - orig_stack_frame)); - while (clone->stack->top != stack_frame) { - Z_ADDREF_PP((zval**)stack_frame); - stack_frame++; - } - } - - /* Add references to loop variables */ - { - zend_uint op_num = execute_data->opline - op_array->opcodes; - - int i; - for (i = 0; i < op_array->last_brk_cont; ++i) { - zend_brk_cont_element *brk_cont = op_array->brk_cont_array + i; - - if (brk_cont->start < 0) { - continue; - } else if (brk_cont->start > op_num) { - break; - } else if (brk_cont->brk > op_num) { - zend_op *brk_opline = op_array->opcodes + brk_cont->brk; - - if (brk_opline->opcode == ZEND_SWITCH_FREE) { - temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var); - - Z_ADDREF_P(var->var.ptr); - } - } - } - } - - /* Update the send_target to use the temporary variable with the same - * offset as the original generator, but in our temporary variable - * memory segment. */ - if (orig->send_target) { - size_t offset = (char *) orig->send_target - (char *)execute_data; - clone->send_target = EX_TMP_VAR(clone->execute_data, offset); - zval_copy_ctor(&clone->send_target->tmp_var); - } - - if (execute_data->current_this) { - clone->execute_data->current_this = execute_data->current_this; - Z_ADDREF_P(execute_data->current_this); - } - } - - /* The value and key are known not to be references, so simply add refs */ - if (orig->value) { - clone->value = orig->value; - Z_ADDREF_P(orig->value); - } - - if (orig->key) { - clone->key = orig->key; - Z_ADDREF_P(orig->key); - } - - return clone_val; -} -/* }}} */ - static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ { zend_generator *generator; @@ -867,7 +698,7 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */ memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); zend_generator_handlers.get_constructor = zend_generator_get_constructor; - zend_generator_handlers.clone_obj = zend_generator_clone; + zend_generator_handlers.clone_obj = NULL; } /* }}} */