Jacek Caban : vbscript: Make vbscode_t own the memory it uses.

Alexandre Julliard julliard at winehq.org
Mon Sep 12 11:42:59 CDT 2011


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Sep 12 12:29:14 2011 +0200

vbscript: Make vbscode_t own the memory it uses.

---

 dlls/vbscript/compile.c       |   33 ++++++++++++++--
 dlls/vbscript/vbscript.h      |   13 ++++++
 dlls/vbscript/vbscript_main.c |   83 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 4 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 181f6c1..450fa18 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -36,6 +36,23 @@ typedef struct {
 
 static HRESULT compile_expression(compile_ctx_t*,expression_t*);
 
+static inline void *compiler_alloc(vbscode_t *vbscode, size_t size)
+{
+    return vbsheap_alloc(&vbscode->heap, size);
+}
+
+static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
+{
+    size_t size;
+    WCHAR *ret;
+
+    size = (strlenW(str)+1)*sizeof(WCHAR);
+    ret = compiler_alloc(vbscode, size);
+    if(ret)
+        memcpy(ret, str, size);
+    return ret;
+}
+
 static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id)
 {
     assert(id < ctx->instr_cnt);
@@ -75,13 +92,18 @@ static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg)
 
 static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
 {
-    unsigned ret;
+    unsigned instr;
+    WCHAR *str;
 
-    ret = push_instr(ctx, op);
-    if(ret == -1)
+    str = compiler_alloc_string(ctx->code, arg);
+    if(!str)
+        return E_OUTOFMEMORY;
+
+    instr = push_instr(ctx, op);
+    if(instr == -1)
         return E_OUTOFMEMORY;
 
-    instr_ptr(ctx, ret)->arg1.str = arg;
+    instr_ptr(ctx, instr)->arg1.str = str;
     return S_OK;
 }
 
@@ -263,6 +285,8 @@ void release_vbscode(vbscode_t *code)
     for(i=0; i < code->bstr_cnt; i++)
         SysFreeString(code->bstr_pool[i]);
 
+    vbsheap_free(&code->heap);
+
     heap_free(code->bstr_pool);
     heap_free(code->source);
     heap_free(code->instrs);
@@ -291,6 +315,7 @@ static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
 
     ctx->instr_cnt = 0;
     ctx->instr_size = 32;
+    vbsheap_init(&ret->heap);
 
     ret->option_explicit = ctx->parser.option_explicit;
 
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 199ca70..9c047d1 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -31,6 +31,18 @@
 #include "wine/list.h"
 #include "wine/unicode.h"
 
+typedef struct {
+    void **blocks;
+    DWORD block_cnt;
+    DWORD last_block;
+    DWORD offset;
+    struct list custom_blocks;
+} vbsheap_t;
+
+void vbsheap_init(vbsheap_t*) DECLSPEC_HIDDEN;
+void *vbsheap_alloc(vbsheap_t*,size_t) __WINE_ALLOC_SIZE(2) DECLSPEC_HIDDEN;
+void vbsheap_free(vbsheap_t*) DECLSPEC_HIDDEN;
+
 typedef struct _function_t function_t;
 typedef struct _vbscode_t vbscode_t;
 typedef struct _script_ctx_t script_ctx_t;
@@ -122,6 +134,7 @@ struct _vbscode_t {
     BSTR *bstr_pool;
     unsigned bstr_pool_size;
     unsigned bstr_cnt;
+    vbsheap_t heap;
 
     struct list entry;
 };
diff --git a/dlls/vbscript/vbscript_main.c b/dlls/vbscript/vbscript_main.c
index 9d74026..1527281 100644
--- a/dlls/vbscript/vbscript_main.c
+++ b/dlls/vbscript/vbscript_main.c
@@ -31,6 +31,89 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
 
 static HINSTANCE vbscript_hinstance;
 
+#define MIN_BLOCK_SIZE  128
+
+static inline DWORD block_size(DWORD block)
+{
+    return MIN_BLOCK_SIZE << block;
+}
+
+void vbsheap_init(vbsheap_t *heap)
+{
+    memset(heap, 0, sizeof(*heap));
+    list_init(&heap->custom_blocks);
+}
+
+void *vbsheap_alloc(vbsheap_t *heap, size_t size)
+{
+    struct list *list;
+    void *tmp;
+
+    size = (size+3)&~3;
+
+    if(!heap->block_cnt) {
+        if(!heap->blocks) {
+            heap->blocks = heap_alloc(sizeof(void*));
+            if(!heap->blocks)
+                return NULL;
+        }
+
+        tmp = heap_alloc(block_size(0));
+        if(!tmp)
+            return NULL;
+
+        heap->blocks[0] = tmp;
+        heap->block_cnt = 1;
+    }
+
+    if(heap->offset + size <= block_size(heap->last_block)) {
+        tmp = ((BYTE*)heap->blocks[heap->last_block])+heap->offset;
+        heap->offset += size;
+        return tmp;
+    }
+
+    if(size <= block_size(heap->last_block+1)) {
+        if(heap->last_block+1 == heap->block_cnt) {
+            tmp = heap_realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*));
+            if(!tmp)
+                return NULL;
+
+            heap->blocks = tmp;
+            heap->blocks[heap->block_cnt] = heap_alloc(block_size(heap->block_cnt));
+            if(!heap->blocks[heap->block_cnt])
+                return NULL;
+
+            heap->block_cnt++;
+        }
+
+        heap->last_block++;
+        heap->offset = size;
+        return heap->blocks[heap->last_block];
+    }
+
+    list = heap_alloc(size + sizeof(struct list));
+    if(!list)
+        return NULL;
+
+    list_add_head(&heap->custom_blocks, list);
+    return list+1;
+}
+
+void vbsheap_free(vbsheap_t *heap)
+{
+    struct list *iter;
+    DWORD i;
+
+    while((iter = list_next(&heap->custom_blocks, &heap->custom_blocks))) {
+        list_remove(iter);
+        heap_free(iter);
+    }
+
+    for(i=0; i < heap->block_cnt; i++)
+        heap_free(heap->blocks[i]);
+    heap_free(heap->blocks);
+}
+
 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
 {
     *ppv = NULL;




More information about the wine-cvs mailing list