Skip to content

Commit d062fb3

Browse files
committed
Generator related fixes
1 parent b7052ef commit d062fb3

File tree

6 files changed

+173
-146
lines changed

6 files changed

+173
-146
lines changed

Zend/zend.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int in
319319
{
320320
zval expr_copy;
321321
int use_copy;
322+
int ret;
322323

323324
zend_make_printable_zval(expr, &expr_copy, &use_copy);
324325
if (use_copy) {
@@ -331,10 +332,11 @@ ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int in
331332
return 0;
332333
}
333334
write_func(Z_STRVAL_P(expr), Z_STRLEN_P(expr));
335+
ret = Z_STRLEN_P(expr);
334336
if (use_copy) {
335337
zval_dtor(expr);
336338
}
337-
return Z_STRLEN_P(expr);
339+
return ret;
338340
}
339341
/* }}} */
340342

@@ -366,7 +368,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */
366368
zend_printf("%s Object (", "Unknown Class");
367369
}
368370
if (class_name) {
369-
efree((char*)class_name);
371+
STR_RELEASE(class_name);
370372
}
371373
if (Z_OBJ_HANDLER_P(expr, get_properties)) {
372374
properties = Z_OBJPROP_P(expr);

Zend/zend_execute.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,9 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
699699
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
700700
return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
701701
}
702+
if (Z_TYPE_P(arg) == IS_REFERENCE) {
703+
arg = Z_REFVAL_P(arg);
704+
}
702705
if (Z_TYPE_P(arg) == IS_OBJECT) {
703706
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
704707
if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
@@ -715,6 +718,9 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
715718
return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
716719
}
717720

721+
if (Z_TYPE_P(arg) == IS_REFERENCE) {
722+
arg = Z_REFVAL_P(arg);
723+
}
718724
if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
719725
return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
720726
}
@@ -1612,19 +1618,19 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
16121618
* and the passed arguments
16131619
*/
16141620
int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
1615-
size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1);
1621+
size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (args_count + 1);
16161622

16171623
total_size += args_size + execute_data_size;
16181624

1619-
EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*));
1625+
EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(zval) - 1)) / sizeof(zval));
16201626
EG(argument_stack)->prev = NULL;
1621-
execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size + vars_size);
1627+
execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + execute_data_size + args_size);
16221628

16231629
/* copy prev_execute_data */
1624-
EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size);
1630+
EX(prev_execute_data) = (zend_execute_data*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
16251631
memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
16261632
EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
1627-
EX(prev_execute_data)->function_state.arguments = (zval*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * args_count);
1633+
EX(prev_execute_data)->function_state.arguments = (zval*)(((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + execute_data_size + args_size - sizeof(zval)));
16281634

16291635
/* copy arguments */
16301636
ZVAL_LONG(EX(prev_execute_data)->function_state.arguments, args_count);

Zend/zend_generators.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
3535
zend_op_array *op_array = execute_data->op_array;
3636

3737
if (generator->send_target) {
38-
Z_DELREF_P(generator->send_target);
38+
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
3939
generator->send_target = NULL;
4040
}
4141

@@ -302,6 +302,9 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
302302
generator->execute_data = execute_data;
303303
generator->stack = EG(argument_stack);
304304
EG(argument_stack) = current_stack;
305+
306+
/* EX(return_value) keeps pointer to zend_object (not a real zval) */
307+
execute_data->return_value = (zval*)generator;
305308
}
306309
/* }}} */
307310

@@ -515,9 +518,8 @@ ZEND_METHOD(Generator, send)
515518

516519
/* Put sent value in the target VAR slot, if it is used */
517520
if (generator->send_target) {
518-
Z_DELREF_P(generator->send_target);
519-
Z_ADDREF_P(value);
520-
ZVAL_COPY_VALUE(generator->send_target, value);
521+
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
522+
ZVAL_COPY(generator->send_target, value);
521523
}
522524

523525
zend_generator_resume(generator TSRMLS_CC);
@@ -672,6 +674,21 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob
672674
}
673675

674676
iterator = &generator->iterator;
677+
678+
//???
679+
#if 1
680+
iterator->intern.std.gc.refcount = 1;
681+
iterator->intern.std.gc.u.v.type = IS_OBJECT;
682+
iterator->intern.std.gc.u.v.flags = 0;
683+
iterator->intern.std.gc.u.v.buffer = 0;
684+
iterator->intern.std.ce = NULL;
685+
iterator->intern.std.properties = NULL;
686+
iterator->intern.std.guards = NULL;
687+
zend_objects_store_put(&iterator->intern.std);
688+
#else
689+
zend_object_std_init(&iterator->intern.std, ???);
690+
#endif
691+
675692
iterator->intern.funcs = &zend_generator_iterator_functions;
676693
iterator->intern.data = (void *) generator;
677694

Zend/zend_iterators.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ static void iter_wrapper_dtor(zend_object *object TSRMLS_DC)
6767

6868
ZEND_API void zend_iterator_wrap(zend_object_iterator *iter, zval *wrapped TSRMLS_DC)
6969
{
70-
ZVAL_OBJ(wrapped, &iter->std);
70+
ZVAL_OBJ(wrapped, &iter->std);
71+
//??? hack (it would be better implement it in anothe way)
72+
Z_OBJ_HT_P(wrapped) = &iterator_object_handlers;
7173
}
7274

7375
ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(

Zend/zend_vm_def.h

+7-7
Original file line numberDiff line numberDiff line change
@@ -2881,8 +2881,8 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
28812881

28822882
ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY)
28832883
{
2884-
/* The generator object is stored in return_value_ptr_ptr */
2885-
zend_generator *generator = (zend_generator *) Z_OBJ_P(EX(return_value));
2884+
/* The generator object is stored in EX(return_value) */
2885+
zend_generator *generator = (zend_generator *) EX(return_value);
28862886

28872887
/* Close the generator to free up resources */
28882888
zend_generator_close(generator, 1 TSRMLS_CC);
@@ -5306,8 +5306,8 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
53065306
{
53075307
USE_OPLINE
53085308

5309-
/* The generator object is stored in return_value_ptr_ptr */
5310-
zend_generator *generator = (zend_generator *) Z_OBJ_P(EX(return_value));
5309+
/* The generator object is stored in EX(return_value) */
5310+
zend_generator *generator = (zend_generator *) EX(return_value);
53115311

53125312
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
53135313
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -5370,7 +5370,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
53705370
) {
53715371
//??? INIT_PZVAL_COPY(copy, value);
53725372
ZVAL_COPY_VALUE(&generator->value, value);
5373-
Z_SET_REFCOUNT(generator->value, 1);
5373+
if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
53745374

53755375
/* Temporary variables don't need ctor copying */
53765376
if (!IS_OP1_TMP_FREE()) {
@@ -5380,7 +5380,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
53805380
FREE_OP1_IF_VAR();
53815381
} else {
53825382
if (OP1_TYPE == IS_CV) {
5383-
Z_ADDREF_P(value);
5383+
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
53845384
}
53855385
ZVAL_COPY_VALUE(&generator->value, value);
53865386
}
@@ -5401,7 +5401,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
54015401
) {
54025402
//??? INIT_PZVAL_COPY(copy, key);
54035403
ZVAL_COPY_VALUE(&generator->key, key);
5404-
Z_SET_REFCOUNT(generator->key, 1);
5404+
if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1);
54055405

54065406
/* Temporary variables don't need ctor copying */
54075407
if (!IS_OP2_TMP_FREE()) {

0 commit comments

Comments
 (0)