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> 2006-04-27 Keith Packard <keithp@keithp.com>
reviewed by: Patrick Lam <plam@mit.edu> reviewed by: Patrick Lam <plam@mit.edu>

View File

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

View File

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

View File

@ -316,374 +316,6 @@ FcPatternDestroy (FcPattern *p)
free (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 static int
FcPatternPosition (const FcPattern *p, const char *object) FcPatternPosition (const FcPattern *p, const char *object)
{ {
@ -1399,8 +1031,6 @@ FcStrStaticNameFini (void)
void void
FcPatternFini (void) FcPatternFini (void)
{ {
FcPatternBaseThawAll ();
FcValueListThawAll ();
FcStrStaticNameFini (); FcStrStaticNameFini ();
FcObjectStaticNameFini (); FcObjectStaticNameFini ();
} }

View File

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