Eliminate pattern freezing
This commit is contained in:
parent
c1c3ba06d5
commit
529291bef4
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
370
src/fcpat.c
370
src/fcpat.c
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1966,8 +1966,7 @@ FcParsePatelt (FcConfigParse *parse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FcVStackPushPattern (parse, FcPatternFreeze(pattern));
|
FcVStackPushPattern (parse, pattern);
|
||||||
FcPatternDestroy (pattern);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue