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>
|
||||
|
||||
reviewed by: Patrick Lam <plam@mit.edu>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -862,9 +862,6 @@ FcPatternAddWithBinding (FcPattern *p,
|
|||
FcValueBinding binding,
|
||||
FcBool append);
|
||||
|
||||
FcPattern *
|
||||
FcPatternFreeze (FcPattern *p);
|
||||
|
||||
void
|
||||
FcPatternFini (void);
|
||||
|
||||
|
|
370
src/fcpat.c
370
src/fcpat.c
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -1966,8 +1966,7 @@ FcParsePatelt (FcConfigParse *parse)
|
|||
}
|
||||
}
|
||||
|
||||
FcVStackPushPattern (parse, FcPatternFreeze(pattern));
|
||||
FcPatternDestroy (pattern);
|
||||
FcVStackPushPattern (parse, pattern);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue