[PATCH v2 02/10] vbscript: Reference count the persistent code list.

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Nov 13 09:24:46 CST 2019


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

This is needed for the TypeInfo since it needs to hold a ref to the
persistent code, too. Though we keep the ref in the script dispatch since
it's more correct this way (even though we bail out when there's no context,
we still technically reference the persistent code funcs/classes in the
dispatch object).

I couldn't refcount the script context itself since it is re-used after being
closed, and was not deemed a good approach to free it (my previous attempts).

 dlls/vbscript/compile.c  |  4 +--
 dlls/vbscript/vbdisp.c   |  4 +++
 dlls/vbscript/vbscript.c | 54 ++++++++++++++++++++++++++++------------
 dlls/vbscript/vbscript.h |  9 ++++++-
 4 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 9ddfacf..6305fe2 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -1778,7 +1778,7 @@ static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifi
             return TRUE;
     }
 
-    LIST_FOR_EACH_ENTRY(code, &script->code_list, vbscode_t, entry) {
+    LIST_FOR_EACH_ENTRY(code, &script->code_list->list, vbscode_t, entry) {
         unsigned var_cnt = code->main_code.var_cnt;
         var_desc_t *vars = code->main_code.vars;
         function_t *func;
@@ -1954,7 +1954,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
     ctx.code = NULL;
     release_compiler(&ctx);
 
-    list_add_tail(&script->code_list, &code->entry);
+    list_add_tail(&script->code_list->list, &code->entry);
     *ret = code;
     return S_OK;
 }
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c
index 8bb2b68..e6a2552 100644
--- a/dlls/vbscript/vbdisp.c
+++ b/dlls/vbscript/vbdisp.c
@@ -589,6 +589,7 @@ static ULONG WINAPI ScriptDisp_Release(IDispatchEx *iface)
         while (!list_empty(&This->code_list))
             release_vbscode(LIST_ENTRY(list_head(&This->code_list), vbscode_t, entry));
 
+        release_code_list(This->persistent_code_list);
         heap_pool_free(&This->heap);
         heap_free(This->global_vars);
         heap_free(This->global_funcs);
@@ -789,6 +790,9 @@ HRESULT create_script_disp(script_ctx_t *ctx, ScriptDisp **ret)
     heap_pool_init(&script_disp->heap);
     list_init(&script_disp->code_list);
 
+    script_disp->persistent_code_list = ctx->code_list;
+    script_disp->persistent_code_list->ref++;
+
     *ret = script_disp;
     return S_OK;
 }
diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c
index 9d20433..6c04781 100644
--- a/dlls/vbscript/vbscript.c
+++ b/dlls/vbscript/vbscript.c
@@ -170,7 +170,7 @@ static void exec_queued_code(script_ctx_t *ctx)
 {
     vbscode_t *iter;
 
-    LIST_FOR_EACH_ENTRY(iter, &ctx->code_list, vbscode_t, entry) {
+    LIST_FOR_EACH_ENTRY(iter, &ctx->code_list->list, vbscode_t, entry) {
         if(iter->pending_exec)
             exec_global_code(ctx, iter, NULL);
     }
@@ -215,17 +215,20 @@ static void release_script(script_ctx_t *ctx)
     collect_objects(ctx);
     clear_ei(&ctx->ei);
 
-    LIST_FOR_EACH_ENTRY_SAFE(code, code_next, &ctx->code_list, vbscode_t, entry)
+    if(ctx->code_list)
     {
-        if(code->is_persistent)
+        LIST_FOR_EACH_ENTRY_SAFE(code, code_next, &ctx->code_list->list, vbscode_t, entry)
         {
-            code->pending_exec = TRUE;
-            if(code->last_class) code->last_class->next = NULL;
-        }
-        else
-        {
-            list_remove(&code->entry);
-            list_add_tail(&ctx->script_obj->code_list, &code->entry);
+            if(code->is_persistent)
+            {
+                code->pending_exec = TRUE;
+                if(code->last_class) code->last_class->next = NULL;
+            }
+            else
+            {
+                list_remove(&code->entry);
+                list_add_tail(&ctx->script_obj->code_list, &code->entry);
+            }
         }
     }
 
@@ -263,10 +266,25 @@ static void release_script(script_ctx_t *ctx)
     }
 }
 
-static void release_code_list(script_ctx_t *ctx)
+static struct ref_list *alloc_code_list(void)
 {
-    while(!list_empty(&ctx->code_list))
-        release_vbscode(LIST_ENTRY(list_head(&ctx->code_list), vbscode_t, entry));
+    struct ref_list *ret = heap_alloc(sizeof(*ret));
+
+    if(ret) {
+        ret->ref = 1;
+        list_init(&ret->list);
+    }
+    return ret;
+}
+
+void release_code_list(struct ref_list *code_list)
+{
+    if(!code_list || --code_list->ref)
+        return;
+
+    while(!list_empty(&code_list->list))
+        release_vbscode(LIST_ENTRY(list_head(&code_list->list), vbscode_t, entry));
+    heap_free(code_list);
 }
 
 static void decrease_state(VBScript *This, SCRIPTSTATE state)
@@ -288,8 +306,10 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state)
             break;
         release_script(This->ctx);
         This->thread_id = 0;
-        if(state == SCRIPTSTATE_CLOSED)
-            release_code_list(This->ctx);
+        if(state == SCRIPTSTATE_CLOSED) {
+            release_code_list(This->ctx->code_list);
+            This->ctx->code_list = NULL;
+        }
         break;
     case SCRIPTSTATE_CLOSED:
         break;
@@ -490,6 +510,9 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
     if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
         return E_UNEXPECTED;
 
+    if(!This->ctx->code_list && !(This->ctx->code_list = alloc_code_list()))
+        return E_OUTOFMEMORY;
+
     hres = create_script_disp(This->ctx, &This->ctx->script_obj);
     if(FAILED(hres))
         return hres;
@@ -1035,7 +1058,6 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pU
 
     ctx->safeopt = INTERFACE_USES_DISPEX;
     list_init(&ctx->objects);
-    list_init(&ctx->code_list);
     list_init(&ctx->named_items);
 
     hres = init_global(ctx);
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 58db0b5..ceca069 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -128,6 +128,11 @@ typedef struct _dynamic_var_t {
     SAFEARRAY *array;
 } dynamic_var_t;
 
+struct ref_list {
+    struct list list;
+    LONG ref;
+};
+
 typedef struct {
     IDispatchEx IDispatchEx_iface;
     LONG ref;
@@ -147,6 +152,7 @@ typedef struct {
     heap_pool_t heap;
 
     struct list code_list;
+    struct ref_list *persistent_code_list;
 } ScriptDisp;
 
 typedef struct _builtin_prop_t builtin_prop_t;
@@ -197,8 +203,8 @@ struct _script_ctx_t {
     EXCEPINFO ei;
 
     struct list objects;
-    struct list code_list;
     struct list named_items;
+    struct ref_list *code_list;
 };
 
 HRESULT init_global(script_ctx_t*) DECLSPEC_HIDDEN;
@@ -358,6 +364,7 @@ struct _vbscode_t {
     struct list entry;
 };
 
+void release_code_list(struct ref_list*) DECLSPEC_HIDDEN;
 void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN;
 HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD,vbscode_t**) DECLSPEC_HIDDEN;
 HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD,class_desc_t**) DECLSPEC_HIDDEN;
-- 
2.21.0




More information about the wine-devel mailing list