Eliminate pattern freezing

This commit is contained in:
Keith Packard 2006-04-27 07:54:07 +00:00
parent c1c3ba06d5
commit 529291bef4
5 changed files with 9 additions and 379 deletions

View File

@ -1,3 +1,11 @@
2006-04-27 Keith Packard <keithp@keithp.com>
* src/fcinit.c: (FcMemReport):
* src/fcint.h:
* src/fcpat.c: (FcPatternFini):
* src/fcxml.c: (FcParsePatelt):
Eliminate pattern freezing
2006-04-27 Keith Packard <keithp@keithp.com>
reviewed by: Patrick Lam <plam@mit.edu>

View File

@ -208,9 +208,6 @@ static int FcMemNotice = 1*1024*1024;
static int FcAllocNotify, FcFreeNotify;
void
FcValueListReport (void);
void
FcMemReport (void)
{
@ -233,7 +230,6 @@ FcMemReport (void)
FcAllocMem - FcFreeMem);
FcAllocNotify = 0;
FcFreeNotify = 0;
FcValueListReport ();
}
void

View File

@ -862,9 +862,6 @@ FcPatternAddWithBinding (FcPattern *p,
FcValueBinding binding,
FcBool append);
FcPattern *
FcPatternFreeze (FcPattern *p);
void
FcPatternFini (void);

View File

@ -316,374 +316,6 @@ FcPatternDestroy (FcPattern *p)
free (p);
}
#define FC_VALUE_LIST_HASH_SIZE 257
#define FC_PATTERN_HASH_SIZE 67
typedef struct _FcValueListEnt FcValueListEnt;
struct _FcValueListEnt {
FcValueListEnt *next;
FcValueListPtr list;
FcChar32 hash, pad;
};
typedef union _FcValueListAlign {
FcValueListEnt ent;
FcValueList list;
} FcValueListAlign;
static int FcValueListFrozenCount[FcTypeLangSet + 1];
static int FcValueListFrozenBytes[FcTypeLangSet + 1];
static const char FcValueListFrozenName[][8] = {
"Void",
"Integer",
"Double",
"String",
"Bool",
"Matrix",
"CharSet",
"FTFace",
"LangSet"
};
void
FcValueListReport (void);
void
FcValueListReport (void)
{
FcType t;
printf ("Fc Frozen Values:\n");
printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
for (t = FcTypeVoid; t <= FcTypeLangSet; t++)
printf ("\t%8s %9d %9d\n", FcValueListFrozenName[t],
FcValueListFrozenCount[t], FcValueListFrozenBytes[t]);
}
static FcValueListEnt *
FcValueListEntCreate (FcValueListPtr h)
{
FcValueListAlign *ea;
FcValueListEnt *e;
FcValueListPtr l;
FcValueList *new;
int n;
int size;
n = 0;
for (l = h; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
n++;
size = sizeof (FcValueListAlign) + n * sizeof (FcValueList);
FcValueListFrozenCount[FcValueListPtrU(h)->value.type]++;
FcValueListFrozenBytes[FcValueListPtrU(h)->value.type] += size;
/* this leaks for some reason */
ea = malloc (sizeof (FcValueListAlign));
if (!ea)
return 0;
new = malloc (n * sizeof (FcValueList));
if (!new)
{
free (ea);
return 0;
}
memset(new, 0, n * sizeof (FcValueList));
FcMemAlloc (FC_MEM_VALLIST, size);
e = &ea->ent;
e->list = FcValueListPtrCreateDynamic(new);
for (l = h; FcValueListPtrU(l);
l = FcValueListPtrU(l)->next, new++)
{
if ((FcValueListPtrU(l)->value.type & ~FC_STORAGE_STATIC) == FcTypeString)
{
new->value.type = FcTypeString;
new->value.u.s = FcStrStaticName
(fc_value_string(&FcValueListPtrU(l)->value));
}
else
{
new->value = FcValueSave (FcValueCanonicalize
(&FcValueListPtrU(l)->value));
}
new->binding = FcValueListPtrU(l)->binding;
if (FcValueListPtrU(FcValueListPtrU(l)->next))
{
new->next = FcValueListPtrCreateDynamic(new + 1);
}
else
{
new->next = FcValueListPtrCreateDynamic(0);
}
}
return e;
}
static void
FcValueListEntDestroy (FcValueListEnt *e)
{
FcValueListPtr l;
FcValueListFrozenCount[FcValueListPtrU(e->list)->value.type]--;
/* XXX: We should perform these two operations with "size" as
computed in FcValueListEntCreate, but we don't have access to
that value here. Without this, the FcValueListFrozenBytes
values will be wrong as will the FcMemFree counts.
FcValueListFrozenBytes[e->list->value.type] -= size;
FcMemFree (FC_MEM_VALLIST, size);
*/
for (l = e->list; FcValueListPtrU(l);
l = FcValueListPtrU(l)->next)
{
if (FcValueListPtrU(l)->value.type != FcTypeString)
FcValueDestroy (FcValueListPtrU(l)->value);
}
/* XXX: Are we being too chummy with the implementation here to
free(e) when it was actually the enclosing FcValueListAlign
that was allocated? */
free (e);
}
static int FcValueListTotal;
static int FcValueListUsed;
static FcValueListEnt *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE];
static FcValueListPtr
FcValueListFreeze (FcValueListPtr l)
{
FcChar32 hash = FcValueListHash (l);
FcValueListEnt **bucket = &FcValueListHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
FcValueListEnt *ent;
FcValueListTotal++;
for (ent = *bucket; ent; ent = ent->next)
{
if (ent->hash == hash && FcValueListEqual (ent->list, l))
return ent->list;
}
ent = FcValueListEntCreate (l);
if (!ent)
return FcValueListPtrCreateDynamic(0);
FcValueListUsed++;
ent->hash = hash;
ent->next = *bucket;
*bucket = ent;
return ent->list;
}
static void
FcValueListThawAll (void)
{
int i;
FcValueListEnt *ent, *next;
for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
{
for (ent = FcValueListHashTable[i]; ent; ent = next)
{
next = ent->next;
FcValueListEntDestroy (ent);
}
FcValueListHashTable[i] = 0;
}
FcValueListTotal = 0;
FcValueListUsed = 0;
}
static FcChar32
FcPatternBaseHash (FcPattern *b)
{
FcChar32 hash = b->num;
int i;
for (i = 0; i < b->num; i++)
hash = ((hash << 1) | (hash >> 31)) ^
(long) (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values));
return hash;
}
typedef struct _FcPatternEnt FcPatternEnt;
struct _FcPatternEnt {
FcPatternEnt *next;
FcChar32 hash;
FcPattern *pattern;
};
static int FcPatternTotal;
static int FcPatternUsed;
static FcPatternEnt *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE];
static FcPattern *
FcPatternBaseFreeze (FcPattern *b)
{
FcPattern *ep;
FcPatternElt *epp;
FcChar32 hash = FcPatternBaseHash (b);
FcPatternEnt **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
FcPatternEnt *ent;
int i;
FcPatternTotal++;
for (ent = *bucket; ent; ent = ent->next)
{
if (ent->hash == hash && b->num == ent->pattern->num)
{
for (i = 0; i < b->num; i++)
{
if (FcObjectPtrCompare((FcPatternEltU(b->elts)+i)->object,
(FcPatternEltU(ent->pattern->elts)+i)->object) != 0)
break;
if (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values) !=
FcValueListPtrU((FcPatternEltU(ent->pattern->elts)+i)->values))
break;
}
if (i == b->num)
return ent->pattern;
}
}
/*
* Compute size of pattern + elts
*/
ent = malloc (sizeof (FcPatternEnt));
if (!ent)
return 0;
FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPatternEnt));
FcPatternUsed++;
ep = FcPatternCreate();
if (!ep)
goto bail;
ent->pattern = ep;
epp = malloc(b->num * sizeof (FcPatternElt));
if (!epp)
{
FcPatternDestroy (ep);
goto bail;
}
ep->elts = FcPatternEltPtrCreateDynamic(epp);
FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num));
ep->num = b->num;
ep->size = b->num;
ep->ref = FC_REF_CONSTANT;
for (i = 0; i < b->num; i++)
{
(FcPatternEltU(ep->elts)+i)->values =
(FcPatternEltU(b->elts)+i)->values;
(FcPatternEltU(ep->elts)+i)->object =
(FcPatternEltU(b->elts)+i)->object;
}
ent->hash = hash;
ent->next = *bucket;
*bucket = ent;
return ent->pattern;
bail:
free(ent);
FcMemFree (FC_MEM_PATTERN, sizeof (FcPatternEnt));
FcPatternUsed--;
return 0;
}
static void
FcPatternBaseThawAll (void)
{
int i;
FcPatternEnt *ent, *next;
for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
{
for (ent = FcPatternHashTable[i]; ent; ent = next)
{
next = ent->next;
free (ent);
}
FcPatternHashTable[i] = 0;
}
FcPatternTotal = 0;
FcPatternUsed = 0;
}
FcPattern *
FcPatternFreeze (FcPattern *p)
{
FcPattern *b, *n = 0, *freeme = 0;
FcPatternElt *e;
int i;
if (p->ref == FC_REF_CONSTANT)
return p;
b = FcPatternCreate();
if (!b)
return 0;
b->num = p->num;
b->size = b->num;
b->ref = 1;
e = malloc(b->num * sizeof (FcPatternElt));
if (!e)
{
FcPatternDestroy (b);
return 0;
}
b->elts = FcPatternEltPtrCreateDynamic(e);
FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num));
/*
* Freeze object lists
*/
for (i = 0; i < p->num; i++)
{
(FcPatternEltU(b->elts)+i)->object =
(FcPatternEltU(p->elts)+i)->object;
(FcPatternEltU(b->elts)+i)->values =
FcValueListFreeze((FcPatternEltU(p->elts)+i)->values);
if (!FcValueListPtrU((FcPatternEltU(p->elts)+i)->values))
{
freeme = b;
goto bail;
}
}
/*
* Freeze base
*/
n = FcPatternBaseFreeze (b);
#ifdef CHATTY
if (FcDebug() & FC_DBG_MEMORY)
{
printf ("ValueLists: total %9d used %9d\n", FcValueListTotal, FcValueListUsed);
printf ("Patterns: total %9d used %9d\n", FcPatternTotal, FcPatternUsed);
}
#endif
bail:
free(FcPatternEltU(b->elts));
b->elts = FcPatternEltPtrCreateDynamic(0);
FcMemFree (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num));
b->num = -1;
if (freeme)
FcPatternDestroy (freeme);
#ifdef DEBUG
assert (FcPatternEqual (n, p));
#endif
return n;
}
static int
FcPatternPosition (const FcPattern *p, const char *object)
{
@ -1399,8 +1031,6 @@ FcStrStaticNameFini (void)
void
FcPatternFini (void)
{
FcPatternBaseThawAll ();
FcValueListThawAll ();
FcStrStaticNameFini ();
FcObjectStaticNameFini ();
}

View File

@ -1966,8 +1966,7 @@ FcParsePatelt (FcConfigParse *parse)
}
}
FcVStackPushPattern (parse, FcPatternFreeze(pattern));
FcPatternDestroy (pattern);
FcVStackPushPattern (parse, pattern);
}
static void