Jacek Caban : jscript: Optimize object refcount handling.

Alexandre Julliard julliard at winehq.org
Fri Oct 26 11:36:21 CDT 2012


Module: wine
Branch: master
Commit: 79a30a4e0ae3a7ef640fa38e3a9f77e1e73cc576
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=79a30a4e0ae3a7ef640fa38e3a9f77e1e73cc576

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Oct 26 13:28:17 2012 +0200

jscript: Optimize object refcount handling.

---

 dlls/jscript/dispex.c  |   78 ++++++++++++++++++++++++++++++------------------
 dlls/jscript/jscript.h |   21 +++++++++++-
 2 files changed, 68 insertions(+), 31 deletions(-)

diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 2a5225f..211ed8a 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -543,46 +543,23 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
         return E_NOINTERFACE;
     }
 
-    IUnknown_AddRef((IUnknown*)*ppv);
+    jsdisp_addref(This);
     return S_OK;
 }
 
 static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
 {
     jsdisp_t *This = impl_from_IDispatchEx(iface);
-    LONG ref = InterlockedIncrement(&This->ref);
-
-    TRACE("(%p) ref=%d\n", This, ref);
-
-    return ref;
+    jsdisp_addref(This);
+    return This->ref;
 }
 
 static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
 {
     jsdisp_t *This = impl_from_IDispatchEx(iface);
-    LONG ref = InterlockedDecrement(&This->ref);
-
-    TRACE("(%p) ref=%d\n", This, ref);
-
-    if(!ref) {
-        dispex_prop_t *prop;
-
-        for(prop = This->props; prop < This->props+This->prop_cnt; prop++) {
-            if(prop->type == PROP_JSVAL)
-                jsval_release(prop->u.val);
-            heap_free(prop->name);
-        }
-        heap_free(This->props);
-        script_release(This->ctx);
-        if(This->prototype)
-            jsdisp_release(This->prototype);
-
-        if(This->builtin_info->destructor)
-            This->builtin_info->destructor(This);
-        else
-            heap_free(This);
-    }
-
+    ULONG ref = --This->ref;
+    if(!ref)
+        jsdisp_free(This);
     return ref;
 }
 
@@ -931,6 +908,49 @@ HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, jsd
     return S_OK;
 }
 
+void jsdisp_free(jsdisp_t *obj)
+{
+    dispex_prop_t *prop;
+
+    TRACE("(%p)\n", obj);
+
+    for(prop = obj->props; prop < obj->props+obj->prop_cnt; prop++) {
+        if(prop->type == PROP_JSVAL)
+            jsval_release(prop->u.val);
+        heap_free(prop->name);
+    }
+    heap_free(obj->props);
+    script_release(obj->ctx);
+    if(obj->prototype)
+        jsdisp_release(obj->prototype);
+
+    if(obj->builtin_info->destructor)
+        obj->builtin_info->destructor(obj);
+    else
+        heap_free(obj);
+}
+
+#ifdef TRACE_REFCNT
+
+jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp)
+{
+    ULONG ref = ++jsdisp->ref;
+    TRACE("(%p) ref=%d\n", jsdisp, ref);
+    return jsdisp;
+}
+
+void jsdisp_release(jsdisp_t *jsdisp)
+{
+    ULONG ref = --jsdisp->ref;
+
+    TRACE("(%p) ref=%d\n", jsdisp, ref);
+
+    if(!ref)
+        jsdisp_free(jsdisp);
+}
+
+#endif
+
 HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *constr)
 {
     jsdisp_t *prot = NULL;
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 2630ff0..18ac1db 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -223,18 +223,35 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp)
 
 jsdisp_t *as_jsdisp(IDispatch*) DECLSPEC_HIDDEN;
 jsdisp_t *to_jsdisp(IDispatch*) DECLSPEC_HIDDEN;
+void jsdisp_free(jsdisp_t*) DECLSPEC_HIDDEN;
 
+#ifndef TRACE_REFCNT
+
+/*
+ * We do a lot of refcount calls during script execution, so having an inline
+ * version is a nice perf win. Define TRACE_REFCNT macro when debugging
+ * refcount bugs to have traces. Also, since jsdisp_t is not thread safe anyways,
+ * there is no point in using atomic operations.
+ */
 static inline jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp)
 {
-    IDispatchEx_AddRef(&jsdisp->IDispatchEx_iface);
+    jsdisp->ref++;
     return jsdisp;
 }
 
 static inline void jsdisp_release(jsdisp_t *jsdisp)
 {
-    IDispatchEx_Release(&jsdisp->IDispatchEx_iface);
+    if(!--jsdisp->ref)
+        jsdisp_free(jsdisp);
 }
 
+#else
+
+jsdisp_t *jsdisp_addref(jsdisp_t*) DECLSPEC_HIDDEN;
+void jsdisp_release(jsdisp_t*) DECLSPEC_HIDDEN;
+
+#endif
+
 HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
 HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN;
 HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list