Drastically simplify and optimize object creation and destruction

Don't populate the typenames array for each and every created object and don't
search it when deleting every object, this is O(N) in number of classes and is
completely impractical for any big library where N can easily be several
thousands. Use destructor function which will correctly destroy the object
instead.

Also don't store each created objects in the global registry, there doesn't
seem to be any point in it.

And, in fact, don't bother with the typenames at all, just use another
pseudo-virtual function for checking whether a class inherits from a class
with the given name.

There is unfortunately one problem with the new approach: it doesn't work when
the same C++ type is wrapped under different names as this results in multiple
specializations of SWIG_derives_from<> for this type. But this is a relatively
rare situation (but which does arise in template_default2 unit test, which had
to be disabled) and could be fixed in the future by completely resolving the
type, including the default template parameters values, and checking if
SWIG_derives_from had been already specialized for it. In the meanwhile, this
regression is not a big deal compared to the advantages of the new approach.
This commit is contained in:
Vadim Zeitlin 2016-04-14 01:41:08 +02:00
commit 818b399c9e
6 changed files with 150 additions and 298 deletions

View file

@ -273,19 +273,16 @@ same_action_all_primitive_types_but_void(out, "$result = $1;")
}
%typemap(out) SWIGTYPE *&, SWIGTYPE ** {
static SwigObj* _ptr = (SwigObj*) SWIG_create_object(SWIG_STR($1_basetype));
static SwigObj* _ptr = (SwigObj*) SWIG_create_object($1, SWIG_STR($1_basetype));
$result = &_ptr;
(*result)->obj = (void*) $1;
}
%typemap(out) SWIGTYPE {
$result = (SwigObj*) SWIG_create_object(SWIG_STR($1_basetype));
$result->obj = (void*) &$1;
$result = (SwigObj*) SWIG_create_object(&$1, SWIG_STR($1_basetype));
}
%typemap(out) SWIGTYPE *, SWIGTYPE & {
$result = (SwigObj*) SWIG_create_object(SWIG_STR($1_basetype));
$result->obj = (void*) $1;
$result = (SwigObj*) SWIG_create_object($1, SWIG_STR($1_basetype));
}
%typemap(out) SWIGTYPE * [ANY], SWIGTYPE [ANY][ANY] {
@ -294,14 +291,13 @@ same_action_all_primitive_types_but_void(out, "$result = $1;")
size_t i = 0;
if (_temp) {
for ( ; i < $1_dim0; ++i)
SWIG_destroy_object(_temp[i]);
SWIG_destroy_object< $1_ltype >(_temp[i]);
free(_temp);
}
_temp = (SwigObj**) malloc($1_dim0 * sizeof(SwigObj*));
for (i = 0 ; i < $1_dim0; ++i) {
if ($1[i]) {
_temp[i] = SWIG_create_object(SWIG_STR($1_ltype));
_temp[i]->obj = (void*) $1[i];
_temp[i] = SWIG_create_object($1[i], SWIG_STR($1_ltype));
}
else
_temp[i] = (SwigObj*) 0;
@ -333,31 +329,48 @@ explicit_same_type_unconsted_all_primitive_types_but_void(cppouttype);
#ifdef SWIG_CPPMODE
#ifdef SWIG_C_EXCEPT
%insert("runtime") %{
typedef struct {
void *obj;
const char **typenames;
const char* symname;
bool (*derives_from)(const char* type);
} SwigObj;
template <class T> SWIGINTERN void SWIG_destroy_object(SwigObj* object) {
if (!object)
return;
delete static_cast<T*>(object->obj);
free(object);
}
template <class T> struct SWIG_derives_from {
static bool check(const char* type) { return false; }
};
template <class T> SWIGINTERN SwigObj* SWIG_create_object(T* obj, const char* symname) {
SwigObj* const result = (SwigObj*)malloc(sizeof(SwigObj));
if (result) {
result->obj = const_cast<void*>(static_cast<const void*>(obj));
result->symname = symname;
result->derives_from = SWIG_derives_from<T>::check;
}
return result;
}
%}
%insert("proxy_header") %{
typedef struct {
void *obj;
const char **typenames;
} SwigObj;
typedef struct SwigObjStruct SwigObj;
%}
#ifdef SWIG_C_EXCEPT
%include "cexcept.swg"
#else
%insert("runtime") %{
typedef struct {
void *obj;
} SwigObj;
#ifdef __cplusplus
extern "C" {
#endif
@ -367,12 +380,6 @@ SWIGEXPORTC int SWIG_exit(int code) { exit(code); }
#endif
%}
%insert("proxy_header") %{
typedef struct {
void *obj;
} SwigObj;
%}
#endif
#else

View file

@ -19,30 +19,24 @@
// this should match only SwigObj objects
%typemap(throws) SWIGTYPE {
SwigObj *c_ex;
c_ex = SWIG_create_object(SWIG_STR($1_basetype));
c_ex->obj = (void*) &$1;
c_ex = SWIG_create_object(&$1, SWIG_STR($1_basetype));
SWIG_CThrowException(c_ex, "C++ $1_type exception thrown");
}
%typemap(throws) SWIGTYPE * {
SwigObj *c_ex;
c_ex = SWIG_create_object(SWIG_STR($1_basetype));
c_ex->obj = (void*) $1;
c_ex = SWIG_create_object($1, SWIG_STR($1_basetype));
SWIG_CThrowException(c_ex, "C++ $1_type exception thrown");
}
%insert("runtime") %{
#include <typeinfo>
SWIGINTERN void SWIG_terminate();
#define SWIG_MAX_RT_STACK 256
#define SWIG_REGISTRY_INIT 256
SWIGINTERN SwigObj **SWIG_registry_base = 0;
SWIGINTERN SwigObj **SWIG_registry = 0;
SWIGINTERN int SWIG_registry_size = SWIG_REGISTRY_INIT;
SWIGINTERN SwigObj *SWIG_create_object(const char *classname);
SWIGINTERN void SWIG_destroy_object(SwigObj *object);
SWIGINTERN void SWIG_free_SwigObj(SwigObj *object);
SWIGEXPORTC struct SWIG_exc_struct {
int code;
char *msg;
@ -51,12 +45,24 @@ SWIGEXPORTC struct SWIG_exc_struct {
} SWIG_exc = { 0, 0, 0, 0 };
SWIGEXPORTC jmp_buf SWIG_rt_env;
SWIGEXPORTC int SWIG_rt_init = 0;
SWIGINTERN jmp_buf SWIG_cpp_back_env;
SWIGINTERN jmp_buf *SWIG_rt_stack_base = 0;
SWIGINTERN jmp_buf *SWIG_rt_stack_ptr = 0;
SWIGINTERN void SWIG_rt_stack_push() {
if (!SWIG_rt_stack_base) {
SWIG_rt_stack_base = SWIG_rt_stack_ptr = (jmp_buf *) malloc(sizeof(jmp_buf) * SWIG_MAX_RT_STACK);
if ((SWIG_exc.code = setjmp(SWIG_rt_env))) {
// deallocate C++ exception
if (setjmp(SWIG_rt_env) == 0) {
SWIG_rt_stack_push();
SWIG_exc.handled = 1;
longjmp(SWIG_cpp_back_env, 1);
}
SWIG_terminate();
}
}
// TODO: check for stack overflow
memcpy(SWIG_rt_stack_ptr, SWIG_rt_env, sizeof(SWIG_rt_env));
SWIG_rt_stack_ptr++;
@ -69,65 +75,14 @@ SWIGINTERN void SWIG_rt_stack_pop() {
memcpy(SWIG_rt_env, SWIG_rt_stack_ptr, sizeof(SWIG_rt_env));
}
SWIGINTERN void SWIG_add_registry_entry(SwigObj *entry) {
if (SWIG_registry_base == 0) {
SWIG_registry_base = SWIG_registry = (SwigObj **) malloc(SWIG_registry_size * sizeof(SwigObj *));
memset(SWIG_registry_base, 0, SWIG_registry_size * sizeof(SwigObj *));
}
*SWIG_registry = entry;
SWIG_registry++;
if ((SWIG_registry - SWIG_registry_base) == SWIG_registry_size) {
SWIG_registry = SWIG_registry_base;
SWIG_registry_size += SWIG_REGISTRY_INIT;
int new_size = SWIG_registry_size * sizeof(SwigObj *);
SWIG_registry_base = (SwigObj **) malloc(new_size);
memset(SWIG_registry_base, 0, new_size);
memcpy(SWIG_registry_base, SWIG_registry, (SWIG_registry_size - SWIG_REGISTRY_INIT) * sizeof(SwigObj *));
free(SWIG_registry);
SWIG_registry = SWIG_registry_base + (SWIG_registry_size - SWIG_REGISTRY_INIT);
}
}
SWIGINTERN void SWIG_remove_registry_entry(SwigObj *entry) {
int i;
for (i = 0; i < SWIG_registry_size; ++i) {
if (*(SWIG_registry_base + i) == entry) {
*(SWIG_registry_base + i) = 0;
break;
}
}
}
SWIGINTERN void SWIG_free_SwigObj(SwigObj *object) {
if (object) {
if (object->typenames)
free(object->typenames);
free(object);
object = (SwigObj *) 0;
}
}
SWIGINTERN void SWIG_cleanup() {
if (SWIG_rt_stack_base)
free(SWIG_rt_stack_base);
if (SWIG_exc.msg)
free(SWIG_exc.msg);
if (SWIG_exc.klass) {
if (SWIG_exc.klass->typenames)
free(SWIG_exc.klass->typenames);
free(SWIG_exc.klass);
}
int i;
if (SWIG_registry_base) {
for (i = 0; i < SWIG_registry_size; ++i) {
if (*(SWIG_registry_base + i)) {
SWIG_free_SwigObj(*(SWIG_registry_base + i));
*(SWIG_registry_base + i) = 0;
}
}
}
free(SWIG_registry_base);
SWIG_registry_base = 0;
}
#ifdef __cplusplus
@ -144,13 +99,7 @@ SWIGEXPORTC int SWIG_rt_catch(const char *type) {
result = 1;
}
else if (SWIG_exc.klass) {
int i = 0;
while (SWIG_exc.klass->typenames[i]) {
if (strcmp(SWIG_exc.klass->typenames[i++], type) == 0) {
result = 1;
break;
}
}
result = strcmp(SWIG_exc.klass->symname, type) == 0 || SWIG_exc.klass->derives_from(type);
}
if (result) {
SWIG_rt_stack_pop();
@ -205,28 +154,11 @@ SWIGEXPORTC int SWIG_exit(int code) {
SWIGINTERN void SWIG_terminate() {
fprintf(stderr, "Unhandled exception: %s\n%s\nExitting...\n",
SWIG_exc.klass->typenames[0],
typeid(*SWIG_exc.klass).name(),
SWIG_exc.msg ? SWIG_exc.msg : "");
SWIG_exit(SWIG_exc.code);
}
SWIGINTERN void SWIG_runtime_init() {
int i, code;
if (!SWIG_rt_init) {
SWIG_rt_init = 1;
SWIG_rt_stack_base = SWIG_rt_stack_ptr = (jmp_buf *) malloc(sizeof(jmp_buf) * SWIG_MAX_RT_STACK);
if ((SWIG_exc.code = setjmp(SWIG_rt_env))) {
// deallocate C++ exception
if (setjmp(SWIG_rt_env) == 0) {
SWIG_rt_stack_push();
SWIG_exc.handled = 1;
longjmp(SWIG_cpp_back_env, 1);
}
SWIG_terminate();
}
}
}
#define SWIG_CThrowException(klass, msg) \
if (setjmp(SWIG_cpp_back_env) == 0) \
SWIG_rt_throw((SwigObj *) klass, msg);