Skip to content

Commit

Permalink
Use static structs for internal classes
Browse files Browse the repository at this point in the history
Except for ArrayAccess, still need to convert some
  • Loading branch information
Girgias committed Jun 8, 2024
1 parent c0e8bd3 commit 6d7fa6c
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 104 deletions.
2 changes: 2 additions & 0 deletions Zend/zend_dimension_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

//BEGIN_EXTERN_C()

#include "zend_types.h"

typedef struct _zend_class_dimensions_functions {
/* rv is a slot provided by the callee that is returned */
zval *(*/* const */ read_dimension)(zend_object *object, zval *offset, zval *rv);
Expand Down
140 changes: 38 additions & 102 deletions Zend/zend_interfaces_dimension.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "zend_alloc.h"
// Assume already included via zend_class_entry definition
//#include "zend_dimension_handlers.h"
// TODO other includes Re zend_callable header to do??

ZEND_API zend_class_entry *zend_ce_arrayaccess;

Expand Down Expand Up @@ -59,11 +58,6 @@ static zval *zend_user_class_read_dimension(zend_object *object, zval *offset, z
return rv;
}

static zval *zend_call_internal_object_handler_read_dimension(zend_object *object, zval *offset, zval *rv)
{
return object->handlers->read_dimension(object, offset, BP_VAR_R, rv);
}

/* rv is a slot provided by the callee that is returned */
static zval *zend_user_class_fetch_dimension(zend_object *object, zval *offset, zval *rv)
{
Expand Down Expand Up @@ -131,46 +125,6 @@ static zval *zend_legacy_ArrayAccess_fetch_append(zend_object *object, zval *rv)
return retval;
}

static zval *zend_call_internal_object_handler_fetch_dimension(zend_object *object, zval *offset, zval *rv)
{
zval *retval;
retval = object->handlers->read_dimension(object, offset, BP_VAR_W, rv);

//ZEND_ASSERT(Z_TYPE_P(retval) != IS_UNDEF)
if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
zend_class_entry *ce = object->ce;

ZVAL_NULL(rv);
retval = rv;
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
} else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
if (!Z_ISREF_P(retval)) {
if (rv != retval) {
ZVAL_COPY(rv, retval);
retval = rv;
}
if (Z_TYPE_P(retval) != IS_OBJECT) {
zend_class_entry *ce = object->ce;
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
ZVAL_NEW_REF(retval, retval);
}
} else {
//if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
// ZVAL_UNREF(retval);
//}
if (rv != retval) {
ZVAL_INDIRECT(rv, retval);
}
}
}
return retval;
}

static zval *zend_call_internal_object_handler_fetch_append(zend_object *object, zval *rv)
{
return zend_call_internal_object_handler_fetch_dimension(object, NULL, rv);
}

static bool zend_user_class_has_dimension(zend_object *object, zval *offset)
{
zend_class_entry *ce = object->ce;
Expand Down Expand Up @@ -199,11 +153,6 @@ static bool zend_user_class_has_dimension(zend_object *object, zval *offset)
return is_set;
}

static bool zend_call_internal_object_handler_has_dimension(zend_object *object, zval *offset)
{
return object->handlers->has_dimension(object, offset, false);
}

static void zend_user_class_write_dimension(zend_object *object, zval *offset, zval *value)
{
zend_class_entry *ce = object->ce;
Expand Down Expand Up @@ -270,16 +219,6 @@ static zval *zend_user_class_fetch_append(zend_object *object, zval *rv)
return rv;
}

static void zend_call_internal_object_handler_write_dimension(zend_object *object, zval *offset, zval *value)
{
object->handlers->write_dimension(object, offset, value);
}

static void zend_call_internal_object_handler_append(zend_object *object, zval *value)
{
object->handlers->write_dimension(object, NULL, value);
}

static void zend_user_class_unset_dimension(zend_object *object, zval *offset)
{
zend_class_entry *ce = object->ce;
Expand All @@ -296,11 +235,6 @@ static void zend_user_class_unset_dimension(zend_object *object, zval *offset)
zval_ptr_dtor(&tmp_offset);
}

static void zend_call_internal_object_handler_unset_dimension(zend_object *object, zval *offset)
{
object->handlers->unset_dimension(object, offset);
}

// TODO Internal classes must define this?
#define ALLOC_HANDLERS_IF_MISSING(dimension_handlers_funcs_ptr, class_ce) \
if (!class_ce->dimension_handlers) { \
Expand Down Expand Up @@ -332,37 +266,29 @@ static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_en

zend_class_dimensions_functions *funcs = NULL;
ALLOC_HANDLERS_IF_MISSING(funcs, class_type);
if (class_type->type == ZEND_INTERNAL_CLASS) {
funcs->read_dimension = zend_call_internal_object_handler_read_dimension;
funcs->has_dimension = zend_call_internal_object_handler_has_dimension;
funcs->fetch_dimension = zend_call_internal_object_handler_fetch_dimension;
funcs->write_dimension = zend_call_internal_object_handler_write_dimension;
funcs->unset_dimension = zend_call_internal_object_handler_unset_dimension;
funcs->append = zend_call_internal_object_handler_append;
funcs->fetch_append = zend_call_internal_object_handler_fetch_append;
} else {
funcs->read_dimension = zend_user_class_read_dimension;
funcs->has_dimension = zend_user_class_has_dimension;
funcs->fetch_dimension = zend_legacy_ArrayAccess_fetch_dimension;
funcs->write_dimension = zend_user_class_write_dimension;
funcs->unset_dimension = zend_user_class_unset_dimension;
funcs->append = zend_legacy_ArrayAccess_append;
funcs->fetch_append = zend_legacy_ArrayAccess_fetch_append;
}

funcs->read_dimension = zend_user_class_read_dimension;
funcs->has_dimension = zend_user_class_has_dimension;
funcs->fetch_dimension = zend_legacy_ArrayAccess_fetch_dimension;
funcs->write_dimension = zend_user_class_write_dimension;
funcs->unset_dimension = zend_user_class_unset_dimension;
funcs->append = zend_legacy_ArrayAccess_append;
funcs->fetch_append = zend_legacy_ArrayAccess_fetch_append;

return SUCCESS;
}

static int zend_implement_dimension_read(zend_class_entry *interface, zend_class_entry *class_type)
{
if (class_type->type == ZEND_INTERNAL_CLASS) {
return SUCCESS;
}

zend_class_dimensions_functions *funcs = NULL;
ALLOC_HANDLERS_IF_MISSING(funcs, class_type);

// TODO: Check if the class that interface implements this relies on the parent handler or not?
if (class_type->type == ZEND_INTERNAL_CLASS) {
funcs->read_dimension = zend_call_internal_object_handler_read_dimension;
funcs->has_dimension = zend_call_internal_object_handler_has_dimension;
} else {
if (!funcs->read_dimension) {
funcs->read_dimension = zend_user_class_read_dimension;
funcs->has_dimension = zend_user_class_has_dimension;
}
Expand All @@ -371,64 +297,74 @@ static int zend_implement_dimension_read(zend_class_entry *interface, zend_class

static int zend_implement_dimension_write(zend_class_entry *interface, zend_class_entry *class_type)
{
if (class_type->type == ZEND_INTERNAL_CLASS) {
return SUCCESS;
}

zend_class_dimensions_functions *funcs = NULL;
ALLOC_HANDLERS_IF_MISSING(funcs, class_type);

if (class_type->type == ZEND_INTERNAL_CLASS) {
funcs->write_dimension = zend_call_internal_object_handler_write_dimension;
} else {
if (!funcs->write_dimension) {
funcs->write_dimension = zend_user_class_write_dimension;
}
return SUCCESS;
}

static int zend_implement_dimension_unset(zend_class_entry *interface, zend_class_entry *class_type)
{
if (class_type->type == ZEND_INTERNAL_CLASS) {
return SUCCESS;
}

zend_class_dimensions_functions *funcs = NULL;
ALLOC_HANDLERS_IF_MISSING(funcs, class_type);

if (class_type->type == ZEND_INTERNAL_CLASS) {
funcs->unset_dimension = zend_call_internal_object_handler_unset_dimension;
} else {
if (!funcs->unset_dimension) {
funcs->unset_dimension = zend_user_class_unset_dimension;
}
return SUCCESS;
}

static int zend_implement_appendable(zend_class_entry *interface, zend_class_entry *class_type)
{
if (class_type->type == ZEND_INTERNAL_CLASS) {
return SUCCESS;
}

zend_class_dimensions_functions *funcs = NULL;
ALLOC_HANDLERS_IF_MISSING(funcs, class_type);

if (class_type->type == ZEND_INTERNAL_CLASS) {
funcs->append = zend_call_internal_object_handler_append;
} else {
if (!funcs->append) {
funcs->append = zend_user_class_append;
}
return SUCCESS;
}

static int zend_implement_dimension_fetch(zend_class_entry *interface, zend_class_entry *class_type)
{
if (class_type->type == ZEND_INTERNAL_CLASS) {
return SUCCESS;
}

zend_class_dimensions_functions *funcs = NULL;
ALLOC_HANDLERS_IF_MISSING(funcs, class_type);

if (class_type->type == ZEND_INTERNAL_CLASS) {
funcs->fetch_dimension = zend_call_internal_object_handler_fetch_dimension;
} else {
if (!funcs->fetch_dimension) {
funcs->fetch_dimension = zend_user_class_fetch_dimension;
}
return SUCCESS;
}

static int zend_implement_dimension_fetch_append(zend_class_entry *interface, zend_class_entry *class_type)
{
if (class_type->type == ZEND_INTERNAL_CLASS) {
return SUCCESS;
}

zend_class_dimensions_functions *funcs = NULL;
ALLOC_HANDLERS_IF_MISSING(funcs, class_type);

if (class_type->type == ZEND_INTERNAL_CLASS) {
funcs->fetch_append = zend_call_internal_object_handler_fetch_append;
} else {
if (!funcs->fetch_append) {
funcs->fetch_append = zend_user_class_fetch_append;
}
return SUCCESS;
Expand Down
7 changes: 5 additions & 2 deletions Zend/zend_opcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ ZEND_API void destroy_zend_class(zval *zv)
if (ce->num_interfaces > 0 && (ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) {
efree(ce->interfaces);
}
if (ce->dimension_handlers) {
efree(ce->dimension_handlers);
}
if (ce->backed_enum_table) {
zend_hash_release(ce->backed_enum_table);
}
Expand Down Expand Up @@ -509,8 +512,8 @@ ZEND_API void destroy_zend_class(zval *zv)
}
if (ce->arrayaccess_funcs_ptr) {
free(ce->arrayaccess_funcs_ptr);
}
if (ce->dimension_handlers) {
// TODO This is a temporary solution
ZEND_ASSERT(ce->dimension_handlers);
free(ce->dimension_handlers);
}
if (ce->num_interfaces > 0) {
Expand Down

0 comments on commit 6d7fa6c

Please sign in to comment.