Browse Source

Fixed calling generators through magic __call()

PHP-7.1.0
Dmitry Stogov 10 years ago
parent
commit
970f21be97
  1. 24
      Zend/tests/generators/generator_trampoline.phpt
  2. 30
      Zend/zend_vm_def.h
  3. 30
      Zend/zend_vm_execute.h

24
Zend/tests/generators/generator_trampoline.phpt

@ -0,0 +1,24 @@
--TEST--
Calling generator through magic __call()
--FILE--
<?php
class A {
public function __call($name, $args) {
for ($i = 0; $i < 5; $i++) {
yield $i;
}
}
}
$a = new A();
foreach ($a->gen() as $n) {
var_dump($n);
}
$a->gen();
?>
--EXPECT--
int(0)
int(1)
int(2)
int(3)
int(4)

30
Zend/zend_vm_def.h

@ -7928,17 +7928,27 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_GENERATOR));
call->symbol_table = NULL;
i_init_func_execute_data(call, &fbc->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
if (ret) {
zend_generator_create_zval(call, &fbc->op_array, ret);
Z_VAR_FLAGS_P(ret) = 0;
} else {
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) {
OBJ_RELEASE((zend_object*)fbc->op_array.prototype);
}
zend_vm_stack_free_args(call);
}
} else {
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
call->symbol_table = NULL;
i_init_func_execute_data(call, &fbc->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
} else {
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
}
} else {
zval retval;

30
Zend/zend_vm_execute.h

@ -1737,17 +1737,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_GENERATOR));
call->symbol_table = NULL;
i_init_func_execute_data(call, &fbc->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
if (ret) {
zend_generator_create_zval(call, &fbc->op_array, ret);
Z_VAR_FLAGS_P(ret) = 0;
} else {
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) {
OBJ_RELEASE((zend_object*)fbc->op_array.prototype);
}
zend_vm_stack_free_args(call);
}
} else {
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
call->symbol_table = NULL;
i_init_func_execute_data(call, &fbc->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
} else {
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
}
} else {
zval retval;

Loading…
Cancel
Save