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