wez             Tue Jan 13 08:38:12 2004 EDT

  Modified files:              
    /php-src/ext/com_dotnet     com_com.c com_extension.c com_handlers.c 
                                php_com_dotnet_internal.h 
  Log:
  Fix leaking constructors.
  Implement a cache for method signatures and DISPID's to
  greatly improve performance when repeatedly accessing
  members with the same names.
  
Index: php-src/ext/com_dotnet/com_com.c
diff -u php-src/ext/com_dotnet/com_com.c:1.9 php-src/ext/com_dotnet/com_com.c:1.10
--- php-src/ext/com_dotnet/com_com.c:1.9        Mon Jan 12 19:40:14 2004
+++ php-src/ext/com_dotnet/com_com.c    Tue Jan 13 08:38:11 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_com.c,v 1.9 2004/01/13 00:40:14 wez Exp $ */
+/* $Id: com_com.c,v 1.10 2004/01/13 13:38:11 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -355,7 +355,17 @@
 {
        OLECHAR *olename;
        HRESULT hr;
+       DISPID *dispid_ptr;
 
+       if (namelen == -1) {
+               namelen = strlen(name);
+       }
+
+       if (obj->id_of_name_cache && SUCCESS == zend_hash_find(obj->id_of_name_cache, 
name, namelen, (void**)&dispid_ptr)) {
+               *dispid = *dispid_ptr;
+               return S_OK;
+       }
+       
        olename = php_com_string_to_olestring(name, namelen, obj->code_page TSRMLS_CC);
 
        if (obj->typeinfo) {
@@ -373,6 +383,15 @@
        }
        efree(olename);
 
+       if (SUCCEEDED(hr)) {
+               /* cache the mapping */
+               if (!obj->id_of_name_cache) {
+                       ALLOC_HASHTABLE(obj->id_of_name_cache);
+                       zend_hash_init(obj->id_of_name_cache, 2, NULL, NULL, 0);
+               }
+               zend_hash_update(obj->id_of_name_cache, name, namelen, dispid, 
sizeof(*dispid), NULL);
+       }
+       
        return hr;
 }
 
@@ -388,7 +407,7 @@
        zend_internal_function *f = 
(zend_internal_function*)EG(function_state_ptr)->function;
 
        /* assumption: that the active function (f) is the function we generated for 
the engine */
-       if (!f || f->type != ZEND_OVERLOADED_FUNCTION_TEMPORARY || f->arg_info == 
NULL) {
+       if (!f || f->arg_info == NULL) {
           f = NULL;
        }
        
Index: php-src/ext/com_dotnet/com_extension.c
diff -u php-src/ext/com_dotnet/com_extension.c:1.7 
php-src/ext/com_dotnet/com_extension.c:1.8
--- php-src/ext/com_dotnet/com_extension.c:1.7  Thu Jan  8 03:14:20 2004
+++ php-src/ext/com_dotnet/com_extension.c      Tue Jan 13 08:38:11 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_extension.c,v 1.7 2004/01/08 08:14:20 andi Exp $ */
+/* $Id: com_extension.c,v 1.8 2004/01/13 13:38:11 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -31,6 +31,7 @@
 
 ZEND_DECLARE_MODULE_GLOBALS(com_dotnet)
 TsHashTable php_com_typelibraries;
+
 zend_class_entry
        *php_com_variant_class_entry,
        *php_com_exception_class_entry,
Index: php-src/ext/com_dotnet/com_handlers.c
diff -u php-src/ext/com_dotnet/com_handlers.c:1.10 
php-src/ext/com_dotnet/com_handlers.c:1.11
--- php-src/ext/com_dotnet/com_handlers.c:1.10  Mon Jan 12 19:40:14 2004
+++ php-src/ext/com_dotnet/com_handlers.c       Tue Jan 13 08:38:11 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_handlers.c,v 1.10 2004/01/13 00:40:14 wez Exp $ */
+/* $Id: com_handlers.c,v 1.11 2004/01/13 13:38:11 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -231,12 +231,21 @@
        return NULL;
 }
 
+static void function_dtor(void *pDest)
+{
+       zend_internal_function *f = (zend_internal_function*)pDest;
+
+       efree(f->function_name);
+       if (f->arg_info) {
+               efree(f->arg_info);
+       }
+}
+
 static union _zend_function *com_method_get(zval *object, char *name, int len 
TSRMLS_DC)
 {
-       zend_internal_function *f;
+       zend_internal_function f, *fptr = NULL;
        php_com_dotnet_object *obj;
-
-       /* TODO: cache this */
+       union _zend_function *func;
 
        obj = CDNO_FETCH(object);
 
@@ -244,64 +253,79 @@
                return NULL;
        }
 
-       f = emalloc(sizeof(zend_internal_function));
-       f->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY;
-       f->num_args = 0;
-       f->arg_info = NULL;
-       f->scope = obj->ce;
-       f->fn_flags = 0;
-       f->function_name = estrndup(name, len);
-
-       if (obj->typeinfo) {
-               /* look for byref params */
-               ITypeComp *comp;
-               ITypeInfo *TI = NULL;
-               DESCKIND kind;
-               BINDPTR bindptr;
-               OLECHAR *olename;
-               ULONG lhash;
-               int i;
-
-               if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) {
-                       olename = php_com_string_to_olestring(name, len, 
obj->code_page TSRMLS_CC);
-                       lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT, 
olename);
-
-                       if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, 
INVOKE_FUNC, &TI, &kind, &bindptr))) {
-                               switch (kind) {
-                                       case DESCKIND_FUNCDESC:
-                                               f->arg_info = 
ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info));
-
-                                               for (i = 0; i < 
bindptr.lpfuncdesc->cParams; i++) {
-                                                       f->arg_info[i].allow_null = 1;
-                                                       if 
(bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) {
-                                                               
f->arg_info[i].pass_by_reference = 1;
+       /* check cache */
+       if (obj->method_cache == NULL || FAILURE == zend_hash_find(obj->method_cache, 
name, len, (void**)&fptr)) {
+               f.type = ZEND_OVERLOADED_FUNCTION;
+               f.num_args = 0;
+               f.arg_info = NULL;
+               f.scope = obj->ce;
+               f.fn_flags = 0;
+               f.function_name = estrndup(name, len);
+
+               if (obj->typeinfo) {
+                       /* look for byref params */
+                       ITypeComp *comp;
+                       ITypeInfo *TI = NULL;
+                       DESCKIND kind;
+                       BINDPTR bindptr;
+                       OLECHAR *olename;
+                       ULONG lhash;
+                       int i;
+
+                       if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) {
+                               olename = php_com_string_to_olestring(name, len, 
obj->code_page TSRMLS_CC);
+                               lhash = LHashValOfNameSys(SYS_WIN32, 
LOCALE_SYSTEM_DEFAULT, olename);
+
+                               if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, 
INVOKE_FUNC, &TI, &kind, &bindptr))) {
+                                       switch (kind) {
+                                               case DESCKIND_FUNCDESC:
+                                                       f.arg_info = 
ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info));
+
+                                                       for (i = 0; i < 
bindptr.lpfuncdesc->cParams; i++) {
+                                                               
f.arg_info[i].allow_null = 1;
+                                                               if 
(bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) {
+                                                                       
f.arg_info[i].pass_by_reference = 1;
+                                                               }
                                                        }
-                                               }
 
-                                               f->num_args = 
bindptr.lpfuncdesc->cParams;
+                                                       f.num_args = 
bindptr.lpfuncdesc->cParams;
 
-                                               ITypeInfo_ReleaseFuncDesc(TI, 
bindptr.lpfuncdesc);
-                                               break;
+                                                       ITypeInfo_ReleaseFuncDesc(TI, 
bindptr.lpfuncdesc);
+                                                       break;
 
-                                       /* these should not happen, but *might* happen 
if the user
-                                        * screws up; lets avoid a leak in that case */
-                                       case DESCKIND_VARDESC:
-                                               ITypeInfo_ReleaseVarDesc(TI, 
bindptr.lpvardesc);
-                                               break;
-                                       case DESCKIND_TYPECOMP:
-                                               ITypeComp_Release(bindptr.lptcomp);
-                                               break;
-                               }
-                               if (TI) {
-                                       ITypeInfo_Release(TI);
+                                                       /* these should not happen, 
but *might* happen if the user
+                                                        * screws up; lets avoid a 
leak in that case */
+                                               case DESCKIND_VARDESC:
+                                                       ITypeInfo_ReleaseVarDesc(TI, 
bindptr.lpvardesc);
+                                                       break;
+                                               case DESCKIND_TYPECOMP:
+                                                       
ITypeComp_Release(bindptr.lptcomp);
+                                                       break;
+                                       }
+                                       if (TI) {
+                                               ITypeInfo_Release(TI);
+                                       }
                                }
+                               ITypeComp_Release(comp);
+                               efree(olename);
                        }
-                       ITypeComp_Release(comp);
-                       efree(olename);
                }
+
+               /* save this method in the cache */
+               if (!obj->method_cache) {
+                       ALLOC_HASHTABLE(obj->method_cache);
+                       zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0);
+               }
+
+               zend_hash_update(obj->method_cache, name, len, &f, sizeof(f), 
(void**)&fptr);
        }
 
-       return (union _zend_function*)f;
+       /* duplicate this into a new chunk of emalloc'd memory,
+        * since the engine will efree it */
+       func = emalloc(sizeof(*fptr));
+       memcpy(func, fptr, sizeof(*fptr));
+
+       return func;
 }
 
 static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
@@ -311,7 +335,7 @@
        int nargs;
        VARIANT v;
        int ret = FAILURE;
-
+       
        obj = CDNO_FETCH(getThis());
 
        if (V_VT(&obj->v) != VT_DISPATCH) {
@@ -343,31 +367,33 @@
 static union _zend_function *com_constructor_get(zval *object TSRMLS_DC)
 {
        php_com_dotnet_object *obj;
-       zend_internal_function *f;
+       static zend_internal_function c, d, v;
 
        obj = CDNO_FETCH(object);
 
-       /* TODO: this leaks */
-       f = emalloc(sizeof(zend_internal_function));
-       f->type = ZEND_INTERNAL_FUNCTION;
-
-       f->function_name = obj->ce->name;
-       f->scope = obj->ce;
-       f->arg_info = NULL;
-       f->num_args = 0;
-       f->fn_flags = 0;
-#if HAVE_MSCOREE_H
-       if (f->function_name[0] == 'd') { /* 'd'otnet */
-               f->handler = ZEND_FN(com_dotnet_create_instance);
-       } else 
-#endif
-       if (f->function_name[0] == 'c') { /* 'c'om */
-               f->handler = ZEND_FN(com_create_instance);
-       } else { /* 'v'ariant */
-               f->handler = ZEND_FN(com_variant_create_instance);
+#define POPULATE_CTOR(f, fn)   \
+       f.type = ZEND_INTERNAL_FUNCTION; \
+       f.function_name = obj->ce->name; \
+       f.scope = obj->ce; \
+       f.arg_info = NULL; \
+       f.num_args = 0; \
+       f.fn_flags = 0; \
+       f.handler = ZEND_FN(fn); \
+       return (union _zend_function*)&f;
+       
+       switch (obj->ce->name[0]) {
+               case 'd':
+                       POPULATE_CTOR(d, com_dotnet_create_instance);
+               
+               case 'c':
+                       POPULATE_CTOR(d, com_create_instance);
+               
+               case 'v':
+                       POPULATE_CTOR(d, com_variant_create_instance);
+                       
+               default:
+                       return NULL;
        }
-
-       return (union _zend_function*)f;
 }
 
 static zend_class_entry *com_class_entry_get(zval *object TSRMLS_DC)
@@ -538,6 +564,13 @@
        }
 
        VariantClear(&obj->v);
+
+       if (obj->method_cache) {
+               FREE_HASHTABLE(obj->method_cache);
+       }
+       if (obj->id_of_name_cache) {
+               FREE_HASHTABLE(obj->id_of_name_cache);
+       }
        efree(obj);
 }
 
Index: php-src/ext/com_dotnet/php_com_dotnet_internal.h
diff -u php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.7 
php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.8
--- php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.7        Mon Jan 12 19:40:14 
2004
+++ php-src/ext/com_dotnet/php_com_dotnet_internal.h    Tue Jan 13 08:38:11 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_com_dotnet_internal.h,v 1.7 2004/01/13 00:40:14 wez Exp $ */
+/* $Id: php_com_dotnet_internal.h,v 1.8 2004/01/13 13:38:11 wez Exp $ */
 
 #ifndef PHP_COM_DOTNET_INTERNAL_H
 #define PHP_COM_DOTNET_INTERNAL_H
@@ -46,6 +46,11 @@
        IDispatch *sink_dispatch;
        GUID sink_id;
        DWORD sink_cookie;
+
+       /* cache for method signatures */
+       HashTable *method_cache;
+       /* cache for name -> DISPID */
+       HashTable *id_of_name_cache;
 } php_com_dotnet_object;
 
 static inline int php_com_is_valid_object(zval *zv TSRMLS_DC)

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to