Skip to content

Commit 3e0412d

Browse files
committed
refactor(reflection): extract declaring-context helpers, add fast-path generic-args lookup
Signed-off-by: azjezz <azjezz@protonmail.com>
1 parent 31dd6b7 commit 3e0412d

1 file changed

Lines changed: 59 additions & 47 deletions

File tree

ext/reflection/php_reflection.c

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,30 @@ static reflection_type_kind get_type_kind(zend_type type) {
15191519
return NAMED_TYPE;
15201520
}
15211521

1522+
static zend_class_entry *reflection_resolve_declaring_class(zend_class_entry *ce)
1523+
{
1524+
return (ce && ce->generic_parameters) ? ce : NULL;
1525+
}
1526+
1527+
static void reflection_resolve_fn_context(
1528+
zend_function *fptr,
1529+
zend_class_entry **declaring_class_out,
1530+
zend_function **declaring_fn_out)
1531+
{
1532+
*declaring_class_out = NULL;
1533+
*declaring_fn_out = NULL;
1534+
if (fptr->type != ZEND_USER_FUNCTION) {
1535+
return;
1536+
}
1537+
1538+
const zend_op_array *op = &fptr->op_array;
1539+
if (op->generic_parameters) {
1540+
*declaring_fn_out = fptr;
1541+
}
1542+
1543+
*declaring_class_out = reflection_resolve_declaring_class(op->scope);
1544+
}
1545+
15221546
/* {{{ reflection_type_factory_ex */
15231547
static void reflection_type_factory_ex(
15241548
zend_type type, zval *object, bool legacy_behavior,
@@ -2856,22 +2880,16 @@ ZEND_METHOD(ReflectionParameter, getType)
28562880
}
28572881

28582882
zend_type pre_erasure = (zend_type) ZEND_TYPE_INIT_NONE(0);
2859-
zend_class_entry *declaring_class = NULL;
2860-
zend_function *declaring_fn = NULL;
2883+
zend_class_entry *declaring_class;
2884+
zend_function *declaring_fn;
2885+
reflection_resolve_fn_context(param->fptr, &declaring_class, &declaring_fn);
28612886
if (param->fptr->type == ZEND_USER_FUNCTION) {
28622887
zend_op_array *op = &param->fptr->op_array;
28632888
if (op->generic_types && op->generic_types->parameters) {
28642889
zend_type *boxed = zend_hash_index_find_ptr(op->generic_types->parameters, param->offset);
28652890
if (boxed) {
28662891
pre_erasure = *boxed;
2867-
declaring_fn = param->fptr;
28682892
}
2869-
} else if (op->generic_parameters) {
2870-
declaring_fn = param->fptr;
2871-
}
2872-
2873-
if (op->scope && op->scope->generic_parameters) {
2874-
declaring_class = op->scope;
28752893
}
28762894
}
28772895

@@ -3749,19 +3767,14 @@ ZEND_METHOD(ReflectionFunctionAbstract, getReturnType)
37493767
}
37503768

37513769
zend_type pre_erasure = (zend_type) ZEND_TYPE_INIT_NONE(0);
3752-
zend_class_entry *declaring_class = NULL;
3753-
zend_function *declaring_fn = NULL;
3770+
zend_class_entry *declaring_class;
3771+
zend_function *declaring_fn;
3772+
reflection_resolve_fn_context(fptr, &declaring_class, &declaring_fn);
37543773
if (fptr->type == ZEND_USER_FUNCTION) {
37553774
zend_op_array *op = &fptr->op_array;
37563775
if (op->generic_types && op->generic_types->return_type) {
37573776
pre_erasure = *op->generic_types->return_type;
37583777
}
3759-
if (op->generic_parameters) {
3760-
declaring_fn = fptr;
3761-
}
3762-
if (op->scope && op->scope->generic_parameters) {
3763-
declaring_class = op->scope;
3764-
}
37653778
}
37663779

37673780
reflection_type_factory_ex(fptr->common.arg_info[-1].type, return_value, true,
@@ -6516,7 +6529,6 @@ ZEND_METHOD(ReflectionProperty, getType)
65166529
}
65176530

65186531
zend_type pre_erasure = (zend_type) ZEND_TYPE_INIT_NONE(0);
6519-
zend_class_entry *declaring_class = NULL;
65206532
zend_class_entry *ce = ref->prop->ce;
65216533
if (ce && ce->generic_types && ce->generic_types->properties) {
65226534
zend_type *boxed = zend_hash_find_ptr(ce->generic_types->properties, ref->prop->name);
@@ -6525,12 +6537,8 @@ ZEND_METHOD(ReflectionProperty, getType)
65256537
}
65266538
}
65276539

6528-
if (ce && ce->generic_parameters) {
6529-
declaring_class = ce;
6530-
}
6531-
65326540
reflection_type_factory_ex(ref->prop->type, return_value, true,
6533-
pre_erasure, declaring_class, NULL);
6541+
pre_erasure, reflection_resolve_declaring_class(ce), NULL);
65346542
}
65356543
/* }}} */
65366544

@@ -8721,6 +8729,24 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForParentClass)
87218729
RETURN_EMPTY_ARRAY();
87228730
}
87238731

8732+
static bool reflection_try_build_named_args_from_table(HashTable *ht, zend_class_entry *ce, zend_string *name, zval *return_value)
8733+
{
8734+
if (!ht) {
8735+
return false;
8736+
}
8737+
8738+
zval *zv;
8739+
ZEND_HASH_FOREACH_VAL(ht, zv) {
8740+
zend_type *boxed = (zend_type *) Z_PTR_P(zv);
8741+
zend_type_named_with_args *named = ZEND_TYPE_NAMED_WITH_ARGS(*boxed);
8742+
if (zend_string_equals_ci(named->name, name)) {
8743+
reflection_build_named_args_list(return_value, boxed, ce);
8744+
return true;
8745+
}
8746+
} ZEND_HASH_FOREACH_END();
8747+
return false;
8748+
}
8749+
87248750
ZEND_METHOD(ReflectionClass, getGenericArgumentsForParentInterface)
87258751
{
87268752
reflection_object *intern;
@@ -8732,6 +8758,11 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForParentInterface)
87328758
ZEND_PARSE_PARAMETERS_END();
87338759
GET_REFLECTION_OBJECT_PTR(ce);
87348760

8761+
HashTable *ht = ce->generic_types ? ce->generic_types->implements : NULL;
8762+
if (reflection_try_build_named_args_from_table(ht, ce, name, return_value)) {
8763+
return;
8764+
}
8765+
87358766
bool is_ancestor = false;
87368767
if (ce->ce_flags & ZEND_ACC_LINKED) {
87378768
for (uint32_t i = 0; i < ce->num_interfaces; i++) {
@@ -8753,18 +8784,6 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForParentInterface)
87538784
"%s is not an ancestor interface of %s", ZSTR_VAL(name), ZSTR_VAL(ce->name));
87548785
RETURN_THROWS();
87558786
}
8756-
8757-
if (ce->generic_types && ce->generic_types->implements) {
8758-
zval *zv;
8759-
ZEND_HASH_FOREACH_VAL(ce->generic_types->implements, zv) {
8760-
zend_type *boxed = (zend_type *) Z_PTR_P(zv);
8761-
zend_type_named_with_args *named = ZEND_TYPE_NAMED_WITH_ARGS(*boxed);
8762-
if (zend_string_equals_ci(named->name, name)) {
8763-
reflection_build_named_args_list(return_value, boxed, ce);
8764-
return;
8765-
}
8766-
} ZEND_HASH_FOREACH_END();
8767-
}
87688787
RETURN_EMPTY_ARRAY();
87698788
}
87708789

@@ -8779,6 +8798,11 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForUsedTrait)
87798798
ZEND_PARSE_PARAMETERS_END();
87808799
GET_REFLECTION_OBJECT_PTR(ce);
87818800

8801+
HashTable *ht = ce->generic_types ? ce->generic_types->trait_uses : NULL;
8802+
if (reflection_try_build_named_args_from_table(ht, ce, name, return_value)) {
8803+
return;
8804+
}
8805+
87828806
bool is_used = false;
87838807
for (uint32_t i = 0; i < ce->num_traits; i++) {
87848808
if (zend_string_equals_ci(ce->trait_names[i].name, name)) {
@@ -8791,18 +8815,6 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForUsedTrait)
87918815
"%s is not a trait used by %s", ZSTR_VAL(name), ZSTR_VAL(ce->name));
87928816
RETURN_THROWS();
87938817
}
8794-
8795-
if (ce->generic_types && ce->generic_types->trait_uses) {
8796-
zval *zv;
8797-
ZEND_HASH_FOREACH_VAL(ce->generic_types->trait_uses, zv) {
8798-
zend_type *boxed = (zend_type *) Z_PTR_P(zv);
8799-
zend_type_named_with_args *named = ZEND_TYPE_NAMED_WITH_ARGS(*boxed);
8800-
if (zend_string_equals_ci(named->name, name)) {
8801-
reflection_build_named_args_list(return_value, boxed, ce);
8802-
return;
8803-
}
8804-
} ZEND_HASH_FOREACH_END();
8805-
}
88068818
RETURN_EMPTY_ARRAY();
88078819
}
88088820

0 commit comments

Comments
 (0)