summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlly Betts <olly@survex.com>2021-12-17 10:11:52 +1300
committerOlly Betts <olly@survex.com>2021-12-17 14:50:49 +1300
commit78f5404727f18e821267b0500e811baf8042d892 (patch)
tree837854ee478071750abe965b8200f2c0cbbdcfa0
parent5da86a14132ae96d885ef12ad04cf771bdb5dd57 (diff)
downloadswig-78f5404727f18e821267b0500e811baf8042d892.tar.gz
Improve generated object handlers
Do more initialisation at module load time. Use a shared set of handlers for cases when the C/C++ object is destroyed with free(). Most of the code in the free_obj and create_object handlers is the same for every wrapped class so factor that out into common functions.
-rw-r--r--Lib/php/phprun.swg21
-rw-r--r--Source/Modules/php.cxx143
2 files changed, 95 insertions, 69 deletions
diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg
index 6f0cc9650..426efe104 100644
--- a/Lib/php/phprun.swg
+++ b/Lib/php/phprun.swg
@@ -206,3 +206,24 @@ static swig_module_info *SWIG_Php_GetModule() {
static void SWIG_Php_SetModule(swig_module_info *pointer, int module_number) {
REGISTER_LONG_CONSTANT(const_name, (long) pointer, CONST_CS | CONST_PERSISTENT);
}
+
+/* Common parts of the "create_object" object handler. */
+static zend_object *SWIG_Php_do_create_object(zend_class_entry *ce, zend_object_handlers *handlers) {
+ swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce);
+ zend_object_std_init(&obj->std, ce);
+ object_properties_init(&obj->std, ce);
+ obj->std.handlers = handlers;
+ obj->newobject = 1;
+ return &obj->std;
+}
+
+/* Common parts of the "free_obj" object handler.
+ Returns void* pointer if the C/C++ object should be destroyed. */
+static void* SWIG_Php_free_obj(zend_object *object) {
+ if (object) {
+ swig_object_wrapper *obj = swig_php_fetch_object(object);
+ zend_object_std_dtor(&obj->std);
+ if (obj->newobject) return obj->ptr;
+ }
+ return NULL;
+}
diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
index 3a62282d8..b83995956 100644
--- a/Source/Modules/php.cxx
+++ b/Source/Modules/php.cxx
@@ -74,9 +74,6 @@ static String *fake_class_name() {
static String *result = NULL;
if (!result) {
result = Len(prefix) ? prefix : module;
- if (!s_creation) {
- s_creation = NewStringEmpty();
- }
if (!fake_cs_entry) {
fake_cs_entry = NewStringf("static zend_function_entry class_%s_functions[] = {\n", result);
}
@@ -116,56 +113,6 @@ extern "C" {
static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
}
-static void print_creation_free_wrapper(Node *n) {
- if (!s_creation) {
- s_creation = NewStringEmpty();
- }
-
- String *s = s_creation;
-
- Printf(s, "/* class entry for %s */\n",class_name);
- Printf(s, "static zend_class_entry *SWIGTYPE_%s_ce;\n\n",class_name);
- Printf(s, "/* class object handlers for %s */\n",class_name);
- Printf(s, "static zend_object_handlers %s_object_handlers;\n\n",class_name);
-
- if (Getattr(n, "has_destructor")) {
- Printf(s, "/* Garbage Collection Method for class %s */\n",class_name);
- Printf(s, "static void %s_free_storage(zend_object *object) {\n",class_name);
- Printf(s, " swig_object_wrapper *obj = 0;\n");
- Printf(s, " if (!object)\n");
- Printf(s, " return;\n");
- Printf(s, " obj = swig_php_fetch_object(object);\n");
-
- Printf(s, " zend_object_std_dtor(&obj->std);\n");
-
- Printf(s, " if (obj->newobject)");
- String *type = Getattr(n, "classtype");
- if (destructor_action) {
- Printv(s,
- " {\n",
- type, " * arg1 = (", type, " *)obj->ptr;\n",
- destructor_action, "\n",
- " }\n", NIL);
- } else if (CPlusPlus) {
- Printf(s, "\n delete (%s *)obj->ptr;\n", type);
- } else {
- Printf(s, "\n free(obj->ptr);\n", type);
- }
- Printf(s, "}\n\n");
- }
-
- Printf(s, "/* Object Creation Method for class %s */\n",class_name);
- Printf(s, "static zend_object *%s_object_new(zend_class_entry *ce) {\n",class_name);
- Printf(s, " swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce);\n");
- Printf(s, " zend_object_std_init(&obj->std, ce);\n");
- Printf(s, " object_properties_init(&obj->std, ce);\n");
- Printf(s, " %s_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n", class_name);
- if (Getattr(n, "has_destructor")) {
- Printf(s, " %s_object_handlers.free_obj = %s_free_storage;\n", class_name, class_name);
- }
- Printf(s, " obj->std.handlers = &%s_object_handlers;\n obj->newobject = 1;\n return &obj->std;\n}\n\n\n",class_name);
-}
-
static void SwigPHP_emit_pointer_type_registrations() {
if (!zend_types)
return;
@@ -208,17 +155,13 @@ static void SwigPHP_emit_pointer_type_registrations() {
Printf(s_wrappers, "}\n\n");
Printf(s_oinit, "\n /* Register classes to represent non-class pointer types */\n");
- Printf(s_oinit, " memcpy(&swig_ptr_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));\n");
+ Printf(s_oinit, " swig_ptr_object_handlers = *zend_get_std_object_handlers();\n");
Printf(s_oinit, " swig_ptr_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n");
Printf(s_oinit, " swig_ptr_object_handlers.cast_object = swig_ptr_cast_object;\n");
while (ki.key) {
String *type = ki.key;
- if (!s_creation) {
- s_creation = NewStringEmpty();
- }
-
Printf(s_creation, "/* class entry for pointer to %s */\n", type);
Printf(s_creation, "zend_class_entry *SWIGTYPE_%s_ce;\n\n", type);
@@ -309,6 +252,7 @@ public:
r_shutdown = NewStringEmpty();
s_header = NewString("/* header section */\n");
s_wrappers = NewString("/* wrapper section */\n");
+ s_creation = NewStringEmpty();
/* subsections of the init section */
s_vdecl = NewString("/* vdecl subsection */\n");
s_cinit = NewString(" /* cinit subsection */\n");
@@ -428,11 +372,9 @@ public:
Language::top(n);
SwigPHP_emit_pointer_type_registrations();
- if (s_creation) {
- Dump(s_creation, s_header);
- Delete(s_creation);
- s_creation = NULL;
- }
+ Dump(s_creation, s_header);
+ Delete(s_creation);
+ s_creation = NULL;
/* start the init section */
{
@@ -1616,9 +1558,75 @@ public:
Delete(interfaces);
}
- Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = %s_object_new;\n", class_name, class_name);
- Printf(s_oinit, " memcpy(&%s_object_handlers,zend_get_std_object_handlers(), sizeof(zend_object_handlers));\n", class_name);
- Printf(s_oinit, " %s_object_handlers.clone_obj = NULL;\n", class_name);
+ Language::classHandler(n);
+
+ static bool emitted_base_object_handlers = false;
+ if (!emitted_base_object_handlers) {
+ Printf(s_creation, "static zend_object_handlers SWIGTYPE_base_object_handlers;\n\n");
+
+ // Set up a base zend_object_handlers structure which we can use as-is
+ // for classes without a destructor, and copy as the basis for other
+ // classes.
+ Printf(s_oinit, " SWIGTYPE_base_object_handlers = *zend_get_std_object_handlers();\n");
+ Printf(s_oinit, " SWIGTYPE_base_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n");
+ Printf(s_oinit, " SWIGTYPE_base_object_handlers.clone_obj = NULL;\n");
+ emitted_base_object_handlers = true;
+ }
+
+ Printf(s_creation, "static zend_class_entry *SWIGTYPE_%s_ce;\n\n", class_name);
+
+ if (Getattr(n, "has_destructor")) {
+ if (destructor_action ? Equal(destructor_action, "free((char *) arg1);") : !CPlusPlus) {
+ // We can use a single function if the destructor action calls free()
+ // (either explicitly or as the default in C-mode) since free() doesn't
+ // care about the object's type. We currently only check for the exact
+ // code that Swig_cdestructor_call() emits.
+ static bool emitted_common_cdestructor = false;
+ if (!emitted_common_cdestructor) {
+ Printf(s_creation, "static zend_object_handlers SWIGTYPE_common_c_object_handlers;\n\n");
+ Printf(s_creation, "static void SWIG_Php_common_c_free_obj(zend_object *object) {free(SWIG_Php_free_obj(object));}\n\n");
+ Printf(s_creation, "static zend_object *SWIG_Php_common_c_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &SWIGTYPE_common_c_object_handlers);}\n");
+
+ Printf(s_oinit, " SWIGTYPE_common_c_object_handlers = SWIGTYPE_base_object_handlers;\n");
+ Printf(s_oinit, " SWIGTYPE_common_c_object_handlers.free_obj = SWIG_Php_common_c_free_obj;\n");
+
+ emitted_common_cdestructor = true;
+ }
+
+ Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_common_c_create_object;\n", class_name);
+ } else {
+ Printf(s_creation, "static zend_object_handlers %s_object_handlers;\n", class_name);
+ Printf(s_creation, "static zend_object *SWIG_Php_create_object_%s(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &%s_object_handlers);}\n", class_name, class_name);
+
+ Printf(s_creation, "static void SWIG_Php_free_obj_%s(zend_object *object) {",class_name);
+ String *type = Getattr(n, "classtype");
+ // Special case handling the delete call generated by
+ // Swig_cppdestructor_call() and generate simpler code.
+ if (destructor_action && !Equal(destructor_action, "delete arg1;")) {
+ Printv(s_creation, "\n"
+ " ", type, " *arg1 = (" , type, " *)SWIG_Php_free_obj(object);\n"
+ " if (arg1) {\n"
+ " ", destructor_action, "\n"
+ " }\n", NIL);
+ } else {
+ Printf(s_creation, "delete (%s *)SWIG_Php_free_obj(object);", type);
+ }
+ Printf(s_creation, "}\n\n");
+
+ Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_create_object_%s;\n", class_name, class_name);
+ Printf(s_oinit, " %s_object_handlers = SWIGTYPE_base_object_handlers;\n", class_name);
+ Printf(s_oinit, " %s_object_handlers.free_obj = SWIG_Php_free_obj_%s;\n", class_name, class_name);
+ }
+ } else {
+ static bool emitted_destructorless_create_object = false;
+ if (!emitted_destructorless_create_object) {
+ emitted_destructorless_create_object = true;
+ Printf(s_creation, "static zend_object *SWIG_Php_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &SWIGTYPE_base_object_handlers);}\n", class_name);
+ }
+
+ Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_create_object;\n", class_name);
+ }
+
// If not defined we aren't wrapping any functions which use this type as a
// parameter or return value, in which case we don't need the clientdata
// set.
@@ -1627,9 +1635,6 @@ public:
Printf(s_oinit, "#endif\n");
Printf(s_oinit, "\n");
- Language::classHandler(n);
-
- print_creation_free_wrapper(n);
generate_magic_property_methods(n, base_class);
Printf(all_cs_entry, " ZEND_FE_END\n};\n\n");