Skip to content

Commit b131bfe

Browse files
committed
bless zend_partial with zend_closure debug info
1 parent c4b2d5f commit b131bfe

File tree

4 files changed

+75
-69
lines changed

4 files changed

+75
-69
lines changed

Zend/tests/partial_function/object-constructor.phpt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,17 @@ catch (RuntimeException $e) {
4747

4848
?>
4949
--EXPECTF--
50-
object(Closure)#%d (1) {
50+
object(Closure)#%d (3) {
51+
["this"]=>
52+
object(Foo)#%d (0) {
53+
}
54+
["parameter"]=>
55+
array(2) {
56+
["$one"]=>
57+
string(10) "<required>"
58+
["$two"]=>
59+
string(10) "<required>"
60+
}
5161
["args"]=>
5262
array(2) {
5363
["one"]=>
@@ -59,7 +69,10 @@ object(Closure)#%d (1) {
5969
Rocking Foo::__construct [1, 2]
6070
object(Foo)#%d (0) {
6171
}
62-
object(Closure)#%d (1) {
72+
object(Closure)#%d (2) {
73+
["this"]=>
74+
object(Bar)#%d (0) {
75+
}
6376
["args"]=>
6477
array(0) {
6578
}

Zend/zend_closures.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_f
553553
/* }}} */
554554

555555
/* *is_temp is int due to Object Handler API */
556-
static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) /* {{{ */
556+
HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) /* {{{ */
557557
{
558558
zend_closure *closure = (zend_closure *)object;
559559
zval val;

Zend/zend_closures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ BEGIN_EXTERN_C()
2929
void zend_register_closure_ce(void);
3030
void zend_closure_bind_var(zval *closure_zv, zend_string *var_name, zval *var);
3131
void zend_closure_bind_var_ex(zval *closure_zv, uint32_t offset, zval *val);
32+
HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp);
3233

3334
extern ZEND_API zend_class_entry *zend_ce_closure;
3435

Zend/zend_partial.c

Lines changed: 58 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,22 @@
2121
#include "zend_closures.h"
2222
#include "zend_partial.h"
2323

24-
zend_object_handlers zend_partial_handlers;
24+
typedef struct _zend_partial {
25+
zend_object std;
26+
zend_function prototype;
27+
zval This;
28+
zend_function func;
29+
zend_function trampoline;
30+
uint32_t argc;
31+
zval *argv;
32+
zend_array *named;
33+
} zend_partial;
34+
35+
static zend_object_handlers zend_partial_handlers;
2536

2637
#define ZEND_PARTIAL_PROPERTY_ERROR() \
2738
zend_throw_error(NULL, "Partial closures cannot have properties")
2839

29-
typedef struct _zend_partial_applied {
30-
zval This;
31-
uint32_t argc;
32-
zval *argv;
33-
zend_array *named;
34-
} zend_partial_applied;
35-
36-
typedef struct _zend_partial {
37-
zend_object std;
38-
zend_function prototype;
39-
zend_function func;
40-
zend_function trampoline;
41-
zend_partial_applied frame;
42-
} zend_partial;
43-
4440
static zend_always_inline zend_object* zend_partial_this(zend_object *object) {
4541
while (object && instanceof_function(object->ce, zend_ce_closure)) {
4642
zend_partial *ptr = (zend_partial*) object;
@@ -49,8 +45,8 @@ static zend_always_inline zend_object* zend_partial_this(zend_object *object) {
4945
break;
5046
}
5147

52-
if (Z_TYPE(ptr->frame.This) == IS_OBJECT) {
53-
object = Z_OBJ(ptr->frame.This);
48+
if (Z_TYPE(ptr->This) == IS_OBJECT) {
49+
object = Z_OBJ(ptr->This);
5450
} else {
5551
object = NULL;
5652
}
@@ -107,8 +103,8 @@ static zend_always_inline void zend_partial_prototype_u(zend_partial *partial, z
107103
partial->prototype.op_array.arg_info++;
108104
}
109105

110-
zval *arg = partial->frame.argv,
111-
*aend = arg + partial->frame.argc;
106+
zval *arg = partial->argv,
107+
*aend = arg + partial->argc;
112108

113109
partial->prototype.common.num_args = 0;
114110

@@ -160,8 +156,8 @@ static zend_always_inline void zend_partial_prototype_i(zend_partial *partial, z
160156
partial->prototype.internal_function.arg_info++;
161157
}
162158

163-
zval *arg = partial->frame.argv,
164-
*aend = arg + partial->frame.argc;
159+
zval *arg = partial->argv,
160+
*aend = arg + partial->argc;
165161

166162
partial->prototype.common.num_args = 0;
167163

@@ -222,8 +218,8 @@ static zend_always_inline zend_object* zend_partial_new(zend_class_entry *type)
222218
}
223219

224220
static zend_always_inline void zend_partial_debug_i(zend_partial *partial, HashTable *ht) {
225-
zval *arg = partial->frame.argv,
226-
*aend = arg + partial->frame.argc;
221+
zval *arg = partial->argv,
222+
*aend = arg + partial->argc;
227223
zend_internal_arg_info *info = partial->func.internal_function.arg_info,
228224
*iend = info + partial->func.internal_function.num_args;
229225

@@ -254,8 +250,8 @@ static zend_always_inline void zend_partial_debug_i(zend_partial *partial, HashT
254250
}
255251

256252
static zend_always_inline void zend_partial_debug_u(zend_partial *partial, HashTable *ht) {
257-
zval *arg = partial->frame.argv,
258-
*aend = arg + partial->frame.argc;
253+
zval *arg = partial->argv,
254+
*aend = arg + partial->argc;
259255
zend_arg_info *info = partial->func.op_array.arg_info,
260256
*iend = info + partial->func.op_array.num_args;
261257

@@ -290,9 +286,7 @@ static HashTable *zend_partial_debug(zend_object *object, int *is_temp) {
290286
zval args;
291287
HashTable *ht;
292288

293-
*is_temp = 1;
294-
295-
ht = zend_new_array(1);
289+
ht = zend_closure_get_debug_info(object, is_temp);
296290

297291
array_init(&args);
298292
zend_hash_update(ht, ZSTR_KNOWN(ZEND_STR_ARGS), &args);
@@ -341,8 +335,8 @@ static HashTable *zend_partial_get_gc(zend_object *obj, zval **table, int *n)
341335
{
342336
zend_partial *partial = (zend_partial *)obj;
343337

344-
*table = Z_TYPE(partial->frame.This) != IS_NULL ? &partial->frame.This : NULL;
345-
*n = Z_TYPE(partial->frame.This) != IS_NULL ? 1 : 0;
338+
*table = Z_TYPE(partial->This) != IS_NULL ? &partial->This : NULL;
339+
*n = Z_TYPE(partial->This) != IS_NULL ? 1 : 0;
346340

347341
return (partial->func.type == ZEND_USER_FUNCTION) ?
348342
ZEND_MAP_PTR_GET(partial->func.op_array.static_variables_ptr) : NULL;
@@ -378,8 +372,8 @@ static int zend_partial_get_trampoline(zend_object *obj, zend_class_entry **ce_p
378372
static void zend_partial_free(zend_object *object) {
379373
zend_partial *partial = (zend_partial*) object;
380374

381-
zval *arg = partial->frame.argv,
382-
*end = arg + partial->frame.argc;
375+
zval *arg = partial->argv,
376+
*end = arg + partial->argc;
383377

384378
while (arg < end) {
385379
if (Z_OPT_REFCOUNTED_P(arg)) {
@@ -388,10 +382,10 @@ static void zend_partial_free(zend_object *object) {
388382
arg++;
389383
}
390384

391-
efree_size(partial->frame.argv, sizeof(zval) * partial->frame.argc);
385+
efree_size(partial->argv, sizeof(zval) * partial->argc);
392386

393-
if (partial->frame.named) {
394-
zend_array_release(partial->frame.named);
387+
if (partial->named) {
388+
zend_array_release(partial->named);
395389
}
396390

397391
zend_arg_info *info = partial->prototype.common.arg_info;
@@ -406,7 +400,7 @@ static void zend_partial_free(zend_object *object) {
406400
destroy_zend_function(&partial->func);
407401
}
408402

409-
zval_ptr_dtor(&partial->frame.This);
403+
zval_ptr_dtor(&partial->This);
410404

411405
zend_object_std_dtor(object);
412406
}
@@ -442,17 +436,17 @@ ZEND_NAMED_FUNCTION(zend_partial_call_magic)
442436

443437
fci.size = sizeof(zend_fcall_info);
444438
fci.retval = return_value;
445-
fci.param_count = MAX(partial->func.common.num_args, partial->frame.argc + num_params);
439+
fci.param_count = MAX(partial->func.common.num_args, partial->argc + num_params);
446440
fci.params = ecalloc(sizeof(zval), fci.param_count);
447441
fcc.function_handler = &partial->func;
448442

449-
if (!Z_ISUNDEF(partial->frame.This)) {
443+
if (!Z_ISUNDEF(partial->This)) {
450444
fci.object =
451445
fcc.object =
452-
zend_partial_this(Z_OBJ(partial->frame.This));
446+
zend_partial_this(Z_OBJ(partial->This));
453447
}
454448

455-
memcpy(fci.params, partial->frame.argv, partial->frame.argc * sizeof(zval));
449+
memcpy(fci.params, partial->argv, partial->argc * sizeof(zval));
456450

457451
zval *arg = fci.params,
458452
*aend = arg + fci.param_count,
@@ -471,14 +465,14 @@ ZEND_NAMED_FUNCTION(zend_partial_call_magic)
471465
arg++;
472466
}
473467

474-
if (partial->frame.named) {
468+
if (partial->named) {
475469
if (!named_args) {
476470
named_args =
477-
partial->frame.named;
471+
partial->named;
478472
GC_ADDREF(named_args);
479473
} else {
480474
HashTable *nested =
481-
zend_array_dup(partial->frame.named);
475+
zend_array_dup(partial->named);
482476

483477
zend_hash_merge(
484478
nested,
@@ -500,7 +494,7 @@ ZEND_NAMED_FUNCTION(zend_partial_call_magic)
500494
}
501495
}
502496

503-
if (partial->frame.named) {
497+
if (partial->named) {
504498
zend_array_release(named_args);
505499
}
506500

@@ -510,7 +504,7 @@ ZEND_NAMED_FUNCTION(zend_partial_call_magic)
510504
zval_ptr_dtor(return_value);
511505

512506
RETVAL_OBJ(
513-
Z_OBJ(partial->frame.This));
507+
Z_OBJ(partial->This));
514508
}
515509

516510
if (!fcc.function_handler) {
@@ -531,61 +525,59 @@ void zend_partial_apply(zval *result, zend_execute_data *call) {
531525
if ((parent = zend_partial_parent(&call->This))) {
532526
function = &parent->func;
533527
prototype = &parent->prototype;
534-
535-
zend_partial_applied *frame = &parent->frame;
536528

537-
partial->frame.argc = frame->argc + ZEND_CALL_NUM_ARGS(call);
538-
partial->frame.argv = ecalloc(partial->frame.argc, sizeof(zval));
529+
partial->argc = parent->argc + ZEND_CALL_NUM_ARGS(call);
530+
partial->argv = ecalloc(partial->argc, sizeof(zval));
539531

540-
memcpy(partial->frame.argv,
541-
frame->argv, frame->argc * sizeof(zval));
532+
memcpy(partial->argv,
533+
parent->argv, parent->argc * sizeof(zval));
542534

543535
uint32_t arg = 0,
544-
aend = frame->argc;
536+
aend = parent->argc;
545537
zval *param = ZEND_CALL_ARG(call, 1),
546538
*pend = param + ZEND_CALL_NUM_ARGS(call);
547539

548540
while (arg < aend && param < pend) {
549-
if (Z_TYPE(partial->frame.argv[arg]) == IS_UNDEF) {
541+
if (Z_TYPE(partial->argv[arg]) == IS_UNDEF) {
550542
if (!Z_ISUNDEF_P(param)) {
551543
ZVAL_COPY_VALUE(
552-
&partial->frame.argv[arg], param);
544+
&partial->argv[arg], param);
553545
}
554546
param++;
555547
}
556548
arg++;
557549
}
558550

559551
if ((ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
560-
if (frame->named) {
561-
partial->frame.named = zend_array_dup(frame->named);
552+
if (parent->named) {
553+
partial->named = zend_array_dup(parent->named);
562554

563555
zend_hash_merge(
564-
partial->frame.named,
556+
partial->named,
565557
call->extra_named_params, zval_copy_ctor, true);
566558
} else {
567-
partial->frame.named =
559+
partial->named =
568560
call->extra_named_params;
569561
GC_ADDREF(call->extra_named_params);
570562
}
571563
}
572564
} else {
573565
function = call->func;
574566

575-
partial->frame.argc = ZEND_CALL_NUM_ARGS(call);
576-
partial->frame.argv = ecalloc(partial->frame.argc, sizeof(zval));
567+
partial->argc = ZEND_CALL_NUM_ARGS(call);
568+
partial->argv = ecalloc(partial->argc, sizeof(zval));
577569

578-
memcpy(partial->frame.argv,
579-
ZEND_CALL_ARG(call, 1), partial->frame.argc * sizeof(zval));
570+
memcpy(partial->argv,
571+
ZEND_CALL_ARG(call, 1), partial->argc * sizeof(zval));
580572

581573
if ((ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
582-
partial->frame.named =
574+
partial->named =
583575
call->extra_named_params;
584576
GC_ADDREF(call->extra_named_params);
585577
}
586578
}
587579

588-
ZVAL_COPY(&partial->frame.This, &call->This);
580+
ZVAL_COPY(&partial->This, &call->This);
589581

590582
memcpy(&partial->func, function,
591583
function->type == ZEND_INTERNAL_FUNCTION ?
@@ -601,7 +593,7 @@ void zend_partial_apply(zval *result, zend_execute_data *call) {
601593

602594
if (partial->func.common.fn_flags & ZEND_ACC_CTOR) {
603595
GC_ADD_FLAGS(
604-
Z_OBJ(partial->frame.This), IS_OBJ_DESTRUCTOR_CALLED);
596+
Z_OBJ(partial->This), IS_OBJ_DESTRUCTOR_CALLED);
605597
}
606598

607599
if (partial->func.type == ZEND_USER_FUNCTION) {

0 commit comments

Comments
 (0)