Skip to content

Commit 8345abc

Browse files
committed
Remove support for cloning generators
1 parent aa791a4 commit 8345abc

10 files changed

+9
-346
lines changed

Zend/tests/generators/clone.phpt

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,15 @@
11
--TEST--
2-
Generators can be cloned
2+
Generators cannot be cloned
33
--FILE--
44
<?php
55

6-
function firstN($end) {
7-
for ($i = 0; $i < $end; ++$i) {
8-
yield $i;
9-
}
6+
function gen() {
7+
yield;
108
}
119

12-
$g1 = firstN(5);
13-
var_dump($g1->current());
14-
$g1->next();
15-
16-
$g2 = clone $g1;
17-
var_dump($g2->current());
18-
$g2->next();
19-
20-
var_dump($g2->current());
21-
var_dump($g1->current());
22-
23-
$g1->next();
24-
var_dump($g1->current());
10+
$gen = gen();
11+
clone $gen;
2512

2613
?>
27-
--EXPECT--
28-
int(0)
29-
int(1)
30-
int(2)
31-
int(1)
32-
int(2)
14+
--EXPECTF--
15+
Fatal error: Trying to clone an uncloneable object of class Generator in %s on line %d

Zend/tests/generators/clone_after_object_call.phpt

Lines changed: 0 additions & 20 deletions
This file was deleted.

Zend/tests/generators/clone_with_foreach.phpt

Lines changed: 0 additions & 33 deletions
This file was deleted.

Zend/tests/generators/clone_with_properties.phpt

Lines changed: 0 additions & 18 deletions
This file was deleted.

Zend/tests/generators/clone_with_stack.phpt

Lines changed: 0 additions & 18 deletions
This file was deleted.

Zend/tests/generators/clone_with_symbol_table.phpt

Lines changed: 0 additions & 27 deletions
This file was deleted.

Zend/tests/generators/clone_with_this.phpt

Lines changed: 0 additions & 24 deletions
This file was deleted.

Zend/tests/generators/nested_method_calls.phpt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ $g2 = gen(new B);
2626
$g2->current();
2727

2828
$g1->next();
29-
30-
$g3 = clone $g2;
31-
unset($g2);
32-
$g3->next();
29+
$g2->next();
3330

3431
?>
3532
--EXPECT--

Zend/tests/generators/yield_during_method_call.phpt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@ $gen = gen();
2222
$gen->rewind();
2323
unset($gen);
2424

25-
// test cloning
26-
$g1 = gen();
27-
$g1->rewind();
28-
$g2 = clone $g1;
29-
unset($g1);
30-
$g2->send('bar');
31-
3225
?>
3326
--EXPECT--
3427
foo
35-
bar

Zend/zend_generators.c

Lines changed: 1 addition & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -196,175 +196,6 @@ static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /*
196196
}
197197
/* }}} */
198198

199-
static zend_object_value zend_generator_clone(zval *object TSRMLS_DC) /* {{{ */
200-
{
201-
zend_generator *orig = zend_object_store_get_object(object TSRMLS_CC);
202-
zend_object_value clone_val = zend_generator_create(Z_OBJCE_P(object) TSRMLS_CC);
203-
zend_generator *clone = zend_object_store_get_object_by_handle(clone_val.handle TSRMLS_CC);
204-
205-
zend_objects_clone_members(
206-
&clone->std, clone_val, &orig->std, Z_OBJ_HANDLE_P(object) TSRMLS_CC
207-
);
208-
209-
clone->execute_data = orig->execute_data;
210-
clone->largest_used_integer_key = orig->largest_used_integer_key;
211-
clone->flags = orig->flags;
212-
213-
if (orig->execute_data) {
214-
/* Create a few shorter aliases to the old execution data */
215-
zend_execute_data *execute_data = orig->execute_data;
216-
zend_op_array *op_array = execute_data->op_array;
217-
HashTable *symbol_table = execute_data->symbol_table;
218-
zend_execute_data *current_execute_data;
219-
zend_op **opline_ptr;
220-
HashTable *current_symbol_table;
221-
zend_vm_stack current_stack;
222-
zval *current_this;
223-
void **stack_frame, **orig_stack_frame;
224-
225-
/* Create new execution context. We have to back up and restore
226-
* EG(current_execute_data), EG(opline_ptr), EG(active_symbol_table)
227-
* and EG(This) here because the function modifies or uses them */
228-
current_execute_data = EG(current_execute_data);
229-
EG(current_execute_data) = execute_data->prev_execute_data;
230-
opline_ptr = EG(opline_ptr);
231-
current_symbol_table = EG(active_symbol_table);
232-
EG(active_symbol_table) = execute_data->symbol_table;
233-
current_this = EG(This);
234-
EG(This) = NULL;
235-
current_stack = EG(argument_stack);
236-
clone->execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC);
237-
clone->stack = EG(argument_stack);
238-
EG(argument_stack) = current_stack;
239-
EG(This) = current_this;
240-
EG(active_symbol_table) = current_symbol_table;
241-
EG(current_execute_data) = current_execute_data;
242-
EG(opline_ptr) = opline_ptr;
243-
244-
/* copy */
245-
clone->execute_data->opline = execute_data->opline;
246-
clone->execute_data->function_state = execute_data->function_state;
247-
clone->execute_data->object = execute_data->object;
248-
clone->execute_data->current_scope = execute_data->current_scope;
249-
clone->execute_data->current_called_scope = execute_data->current_called_scope;
250-
clone->execute_data->fast_ret = execute_data->fast_ret;
251-
252-
if (!symbol_table) {
253-
int i;
254-
255-
/* Copy compiled variables */
256-
for (i = 0; i < op_array->last_var; i++) {
257-
if (*EX_CV_NUM(execute_data, i)) {
258-
*EX_CV_NUM(clone->execute_data, i) = (zval **) EX_CV_NUM(clone->execute_data, op_array->last_var + i);
259-
**EX_CV_NUM(clone->execute_data, i) = *(zval **) EX_CV_NUM(execute_data, op_array->last_var + i);
260-
Z_ADDREF_PP(*EX_CV_NUM(clone->execute_data, i));
261-
}
262-
}
263-
} else {
264-
/* Copy symbol table */
265-
ALLOC_HASHTABLE(clone->execute_data->symbol_table);
266-
zend_hash_init(clone->execute_data->symbol_table, zend_hash_num_elements(symbol_table), NULL, ZVAL_PTR_DTOR, 0);
267-
zend_hash_copy(clone->execute_data->symbol_table, symbol_table, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
268-
269-
/* Update zval** pointers for compiled variables */
270-
{
271-
int i;
272-
for (i = 0; i < op_array->last_var; i++) {
273-
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) {
274-
*EX_CV_NUM(clone->execute_data, i) = NULL;
275-
}
276-
}
277-
}
278-
}
279-
280-
/* Copy nested-calls stack */
281-
if (execute_data->call) {
282-
clone->execute_data->call = clone->execute_data->call_slots +
283-
(execute_data->call - execute_data->call_slots);
284-
} else {
285-
clone->execute_data->call = NULL;
286-
}
287-
memcpy(clone->execute_data->call_slots, execute_data->call_slots, ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls);
288-
if (clone->execute_data->call >= clone->execute_data->call_slots) {
289-
call_slot *call = clone->execute_data->call;
290-
291-
while (call >= clone->execute_data->call_slots) {
292-
if (call->object) {
293-
Z_ADDREF_P(call->object);
294-
}
295-
call--;
296-
}
297-
}
298-
299-
/* Copy the temporary variables */
300-
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);
301-
302-
/* Copy arguments passed on stack */
303-
stack_frame = zend_vm_stack_frame_base(clone->execute_data);
304-
orig_stack_frame = zend_vm_stack_frame_base(execute_data);
305-
clone->stack->top = stack_frame + (orig->stack->top - orig_stack_frame);
306-
if (clone->stack->top != stack_frame) {
307-
memcpy(stack_frame, orig_stack_frame, ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (orig->stack->top - orig_stack_frame));
308-
while (clone->stack->top != stack_frame) {
309-
Z_ADDREF_PP((zval**)stack_frame);
310-
stack_frame++;
311-
}
312-
}
313-
314-
/* Add references to loop variables */
315-
{
316-
zend_uint op_num = execute_data->opline - op_array->opcodes;
317-
318-
int i;
319-
for (i = 0; i < op_array->last_brk_cont; ++i) {
320-
zend_brk_cont_element *brk_cont = op_array->brk_cont_array + i;
321-
322-
if (brk_cont->start < 0) {
323-
continue;
324-
} else if (brk_cont->start > op_num) {
325-
break;
326-
} else if (brk_cont->brk > op_num) {
327-
zend_op *brk_opline = op_array->opcodes + brk_cont->brk;
328-
329-
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
330-
temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
331-
332-
Z_ADDREF_P(var->var.ptr);
333-
}
334-
}
335-
}
336-
}
337-
338-
/* Update the send_target to use the temporary variable with the same
339-
* offset as the original generator, but in our temporary variable
340-
* memory segment. */
341-
if (orig->send_target) {
342-
size_t offset = (char *) orig->send_target - (char *)execute_data;
343-
clone->send_target = EX_TMP_VAR(clone->execute_data, offset);
344-
zval_copy_ctor(&clone->send_target->tmp_var);
345-
}
346-
347-
if (execute_data->current_this) {
348-
clone->execute_data->current_this = execute_data->current_this;
349-
Z_ADDREF_P(execute_data->current_this);
350-
}
351-
}
352-
353-
/* The value and key are known not to be references, so simply add refs */
354-
if (orig->value) {
355-
clone->value = orig->value;
356-
Z_ADDREF_P(orig->value);
357-
}
358-
359-
if (orig->key) {
360-
clone->key = orig->key;
361-
Z_ADDREF_P(orig->key);
362-
}
363-
364-
return clone_val;
365-
}
366-
/* }}} */
367-
368199
static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
369200
{
370201
zend_generator *generator;
@@ -867,7 +698,7 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */
867698

868699
memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
869700
zend_generator_handlers.get_constructor = zend_generator_get_constructor;
870-
zend_generator_handlers.clone_obj = zend_generator_clone;
701+
zend_generator_handlers.clone_obj = NULL;
871702
}
872703
/* }}} */
873704

0 commit comments

Comments
 (0)