oleaut32: Use IMalloc_GetSize to determine the cache bucket.

This also has the effect of ignoring non-allocated memory blocks.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2016-01-21 10:29:51 +00:00 committed by Alexandre Julliard
parent 36f454cda0
commit 924cad5f3b
2 changed files with 41 additions and 5 deletions

View File

@ -120,14 +120,27 @@ static inline bstr_t *bstr_from_str(BSTR str)
return CONTAINING_RECORD(str, bstr_t, u.str);
}
static inline bstr_cache_entry_t *get_cache_entry(size_t size)
static inline bstr_cache_entry_t *get_cache_entry_from_idx(unsigned cache_idx)
{
unsigned cache_idx = FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)-1])/BUCKET_SIZE;
return bstr_cache_enabled && cache_idx < sizeof(bstr_cache)/sizeof(*bstr_cache)
? bstr_cache + cache_idx
: NULL;
}
static inline bstr_cache_entry_t *get_cache_entry(size_t size)
{
unsigned cache_idx = FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)-1])/BUCKET_SIZE;
return get_cache_entry_from_idx(cache_idx);
}
static inline bstr_cache_entry_t *get_cache_entry_from_alloc_size(SIZE_T alloc_size)
{
unsigned cache_idx;
if (alloc_size < BUCKET_SIZE) return NULL;
cache_idx = (alloc_size - BUCKET_SIZE) / BUCKET_SIZE;
return get_cache_entry_from_idx(cache_idx);
}
static bstr_t *alloc_bstr(size_t size)
{
bstr_cache_entry_t *cache_entry = get_cache_entry(size);
@ -234,6 +247,16 @@ BSTR WINAPI SysAllocString(LPCOLESTR str)
return SysAllocStringLen(str, lstrlenW(str));
}
static inline IMalloc *get_malloc(void)
{
static IMalloc *malloc;
if (!malloc)
CoGetMalloc(1, &malloc);
return malloc;
}
/******************************************************************************
* SysFreeString [OLEAUT32.6]
*
@ -253,12 +276,19 @@ void WINAPI SysFreeString(BSTR str)
{
bstr_cache_entry_t *cache_entry;
bstr_t *bstr;
IMalloc *malloc = get_malloc();
SIZE_T alloc_size;
if(!str)
return;
bstr = bstr_from_str(str);
cache_entry = get_cache_entry(bstr->size);
alloc_size = IMalloc_GetSize(malloc, bstr);
if (alloc_size == ~0UL)
return;
cache_entry = get_cache_entry_from_alloc_size(alloc_size);
if(cache_entry) {
unsigned i;

View File

@ -6369,9 +6369,15 @@ static void test_bstr_cache(void)
ok(str == str2, "str != str2\n");
SysFreeString(str2);
/* Fill the bucket with cached entries. */
/* Fill the bucket with cached entries.
We roll our own, to show that the cache doesn't use
the bstr length field to determine bucket allocation. */
for(i=0; i < sizeof(strs)/sizeof(*strs); i++)
strs[i] = SysAllocStringLen(NULL, 24);
{
DWORD_PTR *ptr = CoTaskMemAlloc(64);
ptr[0] = 0;
strs[i] = (BSTR)(ptr + 1);
}
for(i=0; i < sizeof(strs)/sizeof(*strs); i++)
SysFreeString(strs[i]);