Commit ed9d78d2 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

oleaut32: Don't free a string in SysFreeString if it's already in cache.

parent 22c39932
...@@ -90,14 +90,15 @@ typedef struct { ...@@ -90,14 +90,15 @@ typedef struct {
} u; } u;
} bstr_t; } bstr_t;
#define BUCKET_SIZE 16
#define BUCKET_BUFFER_SIZE 6
typedef struct { typedef struct {
unsigned short head; unsigned short head;
unsigned short cnt; unsigned short cnt;
bstr_t *buf[6]; bstr_t *buf[BUCKET_BUFFER_SIZE];
} bstr_cache_entry_t; } bstr_cache_entry_t;
#define BUCKET_SIZE 16
#define ARENA_INUSE_FILLER 0x55 #define ARENA_INUSE_FILLER 0x55
#define ARENA_TAIL_FILLER 0xab #define ARENA_TAIL_FILLER 0xab
#define ARENA_FREE_FILLER 0xfeeefeee #define ARENA_FREE_FILLER 0xfeeefeee
...@@ -138,7 +139,7 @@ static bstr_t *alloc_bstr(size_t size) ...@@ -138,7 +139,7 @@ static bstr_t *alloc_bstr(size_t size)
if(cache_entry) { if(cache_entry) {
ret = cache_entry->buf[cache_entry->head++]; ret = cache_entry->buf[cache_entry->head++];
cache_entry->head %= sizeof(cache_entry->buf)/sizeof(*cache_entry->buf); cache_entry->head %= BUCKET_BUFFER_SIZE;
cache_entry->cnt--; cache_entry->cnt--;
} }
...@@ -257,14 +258,26 @@ void WINAPI SysFreeString(BSTR str) ...@@ -257,14 +258,26 @@ void WINAPI SysFreeString(BSTR str)
bstr = bstr_from_str(str); bstr = bstr_from_str(str);
cache_entry = get_cache_entry(bstr->size+sizeof(WCHAR)); cache_entry = get_cache_entry(bstr->size+sizeof(WCHAR));
if(cache_entry) { if(cache_entry) {
unsigned i;
EnterCriticalSection(&cs_bstr_cache); EnterCriticalSection(&cs_bstr_cache);
/* According to tests, freeing a string that's already in cache doesn't corrupt anything.
* For that to work we need to search the cache. */
for(i=0; i < cache_entry->cnt; i++) {
if(cache_entry->buf[(cache_entry->head+cache_entry->cnt) % BUCKET_BUFFER_SIZE] == bstr) {
WARN_(heap)("String already is in cache!\n");
LeaveCriticalSection(&cs_bstr_cache);
return;
}
}
if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) { if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) {
cache_entry->buf[(cache_entry->head+cache_entry->cnt)%((sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)))] = bstr; cache_entry->buf[(cache_entry->head+cache_entry->cnt) % BUCKET_BUFFER_SIZE] = bstr;
cache_entry->cnt++; cache_entry->cnt++;
if(WARN_ON(heap)) { if(WARN_ON(heap)) {
unsigned i, n = bstr_alloc_size(bstr->size) / sizeof(DWORD) - 1; unsigned n = bstr_alloc_size(bstr->size) / sizeof(DWORD) - 1;
bstr->size = ARENA_FREE_FILLER; bstr->size = ARENA_FREE_FILLER;
for(i=0; i<n; i++) for(i=0; i<n; i++)
bstr->u.dwptr[i] = ARENA_FREE_FILLER; bstr->u.dwptr[i] = ARENA_FREE_FILLER;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment