efl/edje: edje program are static for all object of the same edje collection.

This reduce our waste of memory by 300K in most elementary application. There is
another 400K to win by merging edje signal callback automat.


SVN revision: 83879
This commit is contained in:
Cedric BAIL 2013-02-14 03:36:13 +00:00
parent 4452fad7a3
commit d065dd4750
8 changed files with 179 additions and 164 deletions

View File

@ -1,3 +1,7 @@
2013-02-14 Cedric Bail
* Reduce memory consumption of Edje program handler.
2013-02-14 Jihoon Kim (jihoon)
* edje entry : fix bug not to display preedit string with PREEDIT_TYPE_NONE style

1
NEWS
View File

@ -106,6 +106,7 @@ Improvements:
- french.
* edje entry : Support &, < and > in preedit string
* eina: Eina_Tiler now take tile size into account.
* edje: reduce memory consumption of Edje program handler.
Fixes:
* Fix a memory leak in ecore_con_dns when using ecore_con_server_connect

View File

@ -69,12 +69,69 @@ edje_cache_emp_free(Edje_Part_Collection_Directory_Entry *ce)
ce->ref = NULL;
}
void
_edje_programs_patterns_init(Edje_Part_Collection *edc)
{
Edje_Signals_Sources_Patterns *ssp = &edc->patterns.programs;
Edje_Program **all;
unsigned int i, j;
if (ssp->signals_patterns)
return;
if (getenv("EDJE_DUMP_PROGRAMS"))
{
INF("Group '%s' programs:", edc->part);
#define EDJE_DUMP_PROGRAM(Section) \
for (i = 0; i < edc->programs.Section##_count; i++) \
INF(#Section" for ('%s', '%s')", edc->programs.Section[i]->signal, edc->programs.Section[i]->source);
EDJE_DUMP_PROGRAM(strcmp);
EDJE_DUMP_PROGRAM(strncmp);
EDJE_DUMP_PROGRAM(strrncmp);
EDJE_DUMP_PROGRAM(fnmatch);
EDJE_DUMP_PROGRAM(nocmp);
}
edje_match_program_hash_build(edc->programs.strcmp,
edc->programs.strcmp_count,
&ssp->exact_match);
j = edc->programs.strncmp_count
+ edc->programs.strrncmp_count
+ edc->programs.fnmatch_count
+ edc->programs.nocmp_count;
if (j == 0) return ;
all = malloc(sizeof (Edje_Program *) * j);
if (!all) return ;
j = 0;
/* FIXME: Build specialized data type for each case */
#define EDJE_LOAD_PROGRAMS_ADD(Array, Edc, It, Git, All) \
for (It = 0; It < Edc->programs.Array##_count; ++It, ++Git) \
All[Git] = Edc->programs.Array[It];
EDJE_LOAD_PROGRAMS_ADD(fnmatch, edc, i, j, all);
EDJE_LOAD_PROGRAMS_ADD(strncmp, edc, i, j, all);
EDJE_LOAD_PROGRAMS_ADD(strrncmp, edc, i, j, all);
/* FIXME: Do a special pass for that one */
EDJE_LOAD_PROGRAMS_ADD(nocmp, edc, i, j, all);
ssp->u.programs.globing = all;
ssp->u.programs.count = j;
ssp->signals_patterns = edje_match_programs_signal_init(all, j);
ssp->sources_patterns = edje_match_programs_source_init(all, j);
}
static Edje_Part_Collection *
_edje_file_coll_open(Edje_File *edf, const char *coll)
{
Edje_Part_Collection *edc = NULL;
Edje_Part_Collection_Directory_Entry *ce;
int id = -1, size = 0;
unsigned int n;
Eina_List *l;
char buf[256];
void *data;
@ -163,6 +220,39 @@ _edje_file_coll_open(Edje_File *edf, const char *coll)
ce->ref = edc;
_edje_programs_patterns_init(edc);
n = edc->programs.fnmatch_count +
edc->programs.strcmp_count +
edc->programs.strncmp_count +
edc->programs.strrncmp_count +
edc->programs.nocmp_count;
if (n > 0)
{
Edje_Program *pr;
unsigned int i;
edc->patterns.table_programs = malloc(sizeof(Edje_Program *) * n);
if (edc->patterns.table_programs)
{
edc->patterns.table_programs_size = n;
#define EDJE_LOAD_BUILD_TABLE(Array, Edc, It, Tmp) \
for (It = 0; It < Edc->programs.Array##_count; ++It) \
{ \
Tmp = Edc->programs.Array[It]; \
Edc->patterns.table_programs[Tmp->id] = Tmp; \
}
EDJE_LOAD_BUILD_TABLE(fnmatch, edc, i, pr);
EDJE_LOAD_BUILD_TABLE(strcmp, edc, i, pr);
EDJE_LOAD_BUILD_TABLE(strncmp, edc, i, pr);
EDJE_LOAD_BUILD_TABLE(strrncmp, edc, i, pr);
EDJE_LOAD_BUILD_TABLE(nocmp, edc, i, pr);
}
}
return edc;
}

View File

@ -2860,9 +2860,9 @@ edje_edit_state_name_set(Evas_Object *obj, const char *part, const char *state,
/* update the 'state' field in all programs. update only if program has
a single target */
part_id = _edje_part_id_find(ed, part);
for (i = 0; i < ed->table_programs_size; i++)
for (i = 0; i < ed->collection->patterns.table_programs_size; i++)
{
Edje_Program *epr = ed->table_programs[i];
Edje_Program *epr = ed->collection->patterns.table_programs[i];
if (eina_list_count(epr->targets) == 1)
{
@ -5087,9 +5087,9 @@ _edje_program_id_find(Edje_Edit *eed, const char *program)
Edje_Program *epr;
int i;
for (i = 0; i < eed->base->table_programs_size; i++)
for (i = 0; i < eed->base->collection->patterns.table_programs_size; i++)
{
epr = eed->base->table_programs[i];
epr = eed->base->collection->patterns.table_programs[i];
if (epr->name && !strcmp(epr->name, program))
return epr->id;
}
@ -5106,9 +5106,9 @@ _edje_program_get_byname(Evas_Object *obj, const char *prog_name)
if (!prog_name) return NULL;
for (i = 0; i < ed->table_programs_size; i++)
for (i = 0; i < ed->collection->patterns.table_programs_size; i++)
{
epr = ed->table_programs[i];
epr = ed->collection->patterns.table_programs[i];
if ((epr->name) && (strcmp(epr->name, prog_name) == 0))
return epr;
}
@ -5127,11 +5127,11 @@ edje_edit_programs_list_get(Evas_Object *obj)
//printf("EE: Found %d programs\n", ed->table_programs_size);
for (i = 0; i < ed->table_programs_size; i++)
for (i = 0; i < ed->collection->patterns.table_programs_size; i++)
{
Edje_Program *epr;
epr = ed->table_programs[i];
epr = ed->collection->patterns.table_programs[i];
/* XXX: bad, we miss programs this way, but since you can't access
* them in any way without a name, better ignore them. */
if (!epr->name) continue;
@ -5169,7 +5169,7 @@ edje_edit_program_add(Evas_Object *obj, const char *name)
ed->collection->programs.nocmp[ed->collection->programs.nocmp_count++] = epr;
//Init Edje_Program
epr->id = ed->table_programs_size;
epr->id = ed->collection->patterns.table_programs_size;
epr->name = eina_stringshare_add(name);
epr->signal = NULL;
epr->source = NULL;
@ -5189,14 +5189,14 @@ edje_edit_program_add(Evas_Object *obj, const char *name)
//Update table_programs
ed->table_programs_size++;
ed->table_programs = realloc(ed->table_programs,
sizeof(Edje_Program *) * ed->table_programs_size);
ed->table_programs[epr->id % ed->table_programs_size] = epr;
ed->collection->patterns.table_programs_size++;
ed->collection->patterns.table_programs = realloc(ed->collection->patterns.table_programs,
sizeof(Edje_Program *) * ed->collection->patterns.table_programs_size);
ed->collection->patterns.table_programs[epr->id % ed->collection->patterns.table_programs_size] = epr;
//Update patterns
_edje_programs_patterns_clean(ed);
_edje_programs_patterns_init(ed);
_edje_programs_patterns_clean(ed->collection);
_edje_programs_patterns_init(ed->collection);
return EINA_TRUE;
}
@ -5225,13 +5225,13 @@ edje_edit_program_del(Evas_Object *obj, const char *prog)
_edje_program_remove(ed->collection, epr);
/* fix table program */
if (epr->id != ed->table_programs_size - 1)
if (epr->id != ed->collection->patterns.table_programs_size - 1)
{
/* If the removed program is not the last in the list/table,
* put the last one in its place and update references to it later */
ed->table_programs[epr->id] = ed->table_programs[ed->table_programs_size - 1];
old_id = ed->table_programs_size - 1;
ed->table_programs[epr->id]->id = epr->id;
ed->collection->patterns.table_programs[epr->id] = ed->collection->patterns.table_programs[ed->collection->patterns.table_programs_size - 1];
old_id = ed->collection->patterns.table_programs_size - 1;
ed->collection->patterns.table_programs[epr->id]->id = epr->id;
}
ps = eina_hash_find(eed->program_scripts, &id);
@ -5280,14 +5280,14 @@ edje_edit_program_del(Evas_Object *obj, const char *prog)
free(pa);
free(epr);
ed->table_programs_size--;
ed->table_programs = realloc(ed->table_programs,
sizeof(Edje_Program *) * ed->table_programs_size);
ed->collection->patterns.table_programs_size--;
ed->collection->patterns.table_programs = realloc(ed->collection->patterns.table_programs,
sizeof(Edje_Program *) * ed->collection->patterns.table_programs_size);
//We also update all other programs that point to old_id and id
for (i = 0; i < ed->table_programs_size; i++)
for (i = 0; i < ed->collection->patterns.table_programs_size; i++)
{
p = ed->table_programs[i];
p = ed->collection->patterns.table_programs[i];
/* check in afters */
EINA_LIST_FOREACH_SAFE(p->after, l, l_next, pa)
@ -5399,8 +5399,8 @@ edje_edit_program_source_set(Evas_Object *obj, const char *prog, const char *sou
_edje_program_insert(ed->collection, epr);
//Update patterns
_edje_programs_patterns_clean(ed);
_edje_programs_patterns_init(ed);
_edje_programs_patterns_clean(ed->collection);
_edje_programs_patterns_init(ed->collection);
return EINA_TRUE;
}
@ -5490,8 +5490,8 @@ edje_edit_program_signal_set(Evas_Object *obj, const char *prog, const char *sig
_edje_program_insert(ed->collection, epr);
//Update patterns
_edje_programs_patterns_clean(ed);
_edje_programs_patterns_init(ed);
_edje_programs_patterns_clean(ed->collection);
_edje_programs_patterns_init(ed->collection);
return EINA_TRUE;
}
@ -5780,7 +5780,7 @@ edje_edit_program_targets_get(Evas_Object *obj, const char *prog)
/* the target is a program */
Edje_Program *p;
p = ed->table_programs[t->id % ed->table_programs_size];
p = ed->collection->patterns.table_programs[t->id % ed->collection->patterns.table_programs_size];
if (p && p->name)
targets = eina_list_append(targets,
eina_stringshare_add(p->name));
@ -5907,7 +5907,7 @@ edje_edit_program_afters_get(Evas_Object *obj, const char *prog)
{
Edje_Program *p = NULL;
p = ed->table_programs[a->id % ed->table_programs_size];
p = ed->collection->patterns.table_programs[a->id % ed->collection->patterns.table_programs_size];
if (p && p->name)
{
//printf(" a: %d name: %s\n", a->id, p->name);
@ -6466,7 +6466,7 @@ _edje_edit_embryo_rebuild(Edje_Edit *eed)
free(ps->processed);
ps->processed = NULL;
}
epr = eed->base->table_programs[ps->id];
epr = eed->base->collection->patterns.table_programs[ps->id];
if (!ps->processed)
ps->processed = _edje_edit_script_process(eed, epr->name, ps->code);
if (!ps->processed)

View File

@ -883,9 +883,9 @@ _edje_embryo_fn_get_program_id(Embryo_Program *ep, Embryo_Cell *params)
ed = embryo_program_data_get(ep);
GETSTR(p, params[1]);
if (!p) return -1;
prog = ed->table_programs;
prog = ed->collection->patterns.table_programs;
if (!prog) return -1;
for (i = 0; i < ed->table_programs_size; i++, prog++)
for (i = 0; i < ed->collection->patterns.table_programs_size; i++, prog++)
{
if (!(*prog)->name) continue;
if (!strcmp((*prog)->name, p)) return (*prog)->id;
@ -1055,7 +1055,7 @@ _edje_embryo_fn_run_program(Embryo_Program *ep, Embryo_Cell *params)
ed = embryo_program_data_get(ep);
program_id = params[1];
if (program_id < 0) return 0;
pr = ed->table_programs[program_id % ed->table_programs_size];
pr = ed->collection->patterns.table_programs[program_id % ed->collection->patterns.table_programs_size];
if (pr)
{
_edje_program_run(ed, pr, 0, "", "");

View File

@ -268,72 +268,17 @@ edje_file_data_get(const char *file, const char *key)
}
void
_edje_programs_patterns_clean(Edje *ed)
_edje_programs_patterns_clean(Edje_Part_Collection *edc)
{
_edje_signals_sources_patterns_clean(&ed->patterns.programs);
_edje_signals_sources_patterns_clean(&edc->patterns.programs);
eina_rbtree_delete(ed->patterns.programs.exact_match,
eina_rbtree_delete(edc->patterns.programs.exact_match,
EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
NULL);
ed->patterns.programs.exact_match = NULL;
edc->patterns.programs.exact_match = NULL;
free(ed->patterns.programs.u.programs.globing);
ed->patterns.programs.u.programs.globing = NULL;
}
void
_edje_programs_patterns_init(Edje *ed)
{
Edje_Signals_Sources_Patterns *ssp = &ed->patterns.programs;
Edje_Program **all;
unsigned int i, j;
if (ssp->signals_patterns)
return;
if (getenv("EDJE_DUMP_PROGRAMS"))
{
INF("Group '%s' programs:", ed->group);
#define EDJE_DUMP_PROGRAM(Section) \
for (i = 0; i < ed->collection->programs.Section##_count; i++) \
INF(#Section" for ('%s', '%s')", ed->collection->programs.Section[i]->signal, ed->collection->programs.Section[i]->source);
EDJE_DUMP_PROGRAM(strcmp);
EDJE_DUMP_PROGRAM(strncmp);
EDJE_DUMP_PROGRAM(strrncmp);
EDJE_DUMP_PROGRAM(fnmatch);
EDJE_DUMP_PROGRAM(nocmp);
}
edje_match_program_hash_build(ed->collection->programs.strcmp,
ed->collection->programs.strcmp_count,
&ssp->exact_match);
j = ed->collection->programs.strncmp_count
+ ed->collection->programs.strrncmp_count
+ ed->collection->programs.fnmatch_count
+ ed->collection->programs.nocmp_count;
if (j == 0) return ;
all = malloc(sizeof (Edje_Program *) * j);
if (!all) return ;
j = 0;
/* FIXME: Build specialized data type for each case */
#define EDJE_LOAD_PROGRAMS_ADD(Array, Ed, It, Git, All) \
for (It = 0; It < Ed->collection->programs.Array##_count; ++It, ++Git) \
All[Git] = Ed->collection->programs.Array[It];
EDJE_LOAD_PROGRAMS_ADD(fnmatch, ed, i, j, all);
EDJE_LOAD_PROGRAMS_ADD(strncmp, ed, i, j, all);
EDJE_LOAD_PROGRAMS_ADD(strrncmp, ed, i, j, all);
/* FIXME: Do a special pass for that one */
EDJE_LOAD_PROGRAMS_ADD(nocmp, ed, i, j, all);
ssp->u.programs.globing = all;
ssp->u.programs.count = j;
ssp->signals_patterns = edje_match_programs_signal_init(all, j);
ssp->sources_patterns = edje_match_programs_source_init(all, j);
free(edc->patterns.programs.u.programs.globing);
edc->patterns.programs.u.programs.globing = NULL;
}
#ifdef HAVE_EPHYSICS
@ -791,36 +736,6 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
}
}
_edje_programs_patterns_init(ed);
n = ed->collection->programs.fnmatch_count +
ed->collection->programs.strcmp_count +
ed->collection->programs.strncmp_count +
ed->collection->programs.strrncmp_count +
ed->collection->programs.nocmp_count;
if (n > 0)
{
Edje_Program *pr;
ed->table_programs = malloc(sizeof(Edje_Program *) * n);
if (ed->table_programs)
{
ed->table_programs_size = n;
#define EDJE_LOAD_BUILD_TABLE(Array, Ed, It, Tmp) \
for (It = 0; It < Ed->collection->programs.Array##_count; ++It) \
{ \
Tmp = Ed->collection->programs.Array[It]; \
Ed->table_programs[Tmp->id] = Tmp; \
}
EDJE_LOAD_BUILD_TABLE(fnmatch, ed, i, pr);
EDJE_LOAD_BUILD_TABLE(strcmp, ed, i, pr);
EDJE_LOAD_BUILD_TABLE(strncmp, ed, i, pr);
EDJE_LOAD_BUILD_TABLE(strrncmp, ed, i, pr);
EDJE_LOAD_BUILD_TABLE(nocmp, ed, i, pr);
}
}
_edje_ref(ed);
_edje_block(ed);
_edje_freeze(ed);
@ -1273,7 +1188,6 @@ _edje_file_del(Edje *ed)
_edje_message_del(ed);
_edje_block_violate(ed);
_edje_var_shutdown(ed);
_edje_programs_patterns_clean(ed);
// if (ed->collection)
// {
// if (ed->collection->script) _edje_embryo_script_shutdown(ed);
@ -1448,9 +1362,6 @@ _edje_file_del(Edje *ed)
if (ed->table_parts) free(ed->table_parts);
ed->table_parts = NULL;
ed->table_parts_size = 0;
if (ed->table_programs) free(ed->table_programs);
ed->table_programs = NULL;
ed->table_programs_size = 0;
ed->focused_part = NULL;
if (tev)
{
@ -1644,6 +1555,11 @@ _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec, Edje_Part_Collec
eina_hash_free(ec->prog_cache.matches);
}
#endif
_edje_programs_patterns_clean(ec);
if (ec->patterns.table_programs) free(ec->patterns.table_programs);
ec->patterns.table_programs = NULL;
ec->patterns.table_programs_size = 0;
if (ec->script) embryo_program_free(ec->script);
_edje_lua2_script_unload(ec);

View File

@ -320,6 +320,7 @@ typedef struct _Edje_Var_Pool Edje_Var_Pool;
typedef struct _Edje_Signal_Source_Char Edje_Signal_Source_Char;
typedef struct _Edje_Text_Insert_Filter_Callback Edje_Text_Insert_Filter_Callback;
typedef struct _Edje_Markup_Filter_Callback Edje_Markup_Filter_Callback;
typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns;
#define EDJE_INF_MAX_W 100000
#define EDJE_INF_MAX_H 100000
@ -767,6 +768,24 @@ struct _Edje_Part_Limit
Edje_Part_Limit_State height; /* -1, 0, or 1 */
};
struct _Edje_Signals_Sources_Patterns
{
Edje_Patterns *signals_patterns;
Edje_Patterns *sources_patterns;
Eina_Rbtree *exact_match;
union {
struct {
Edje_Program **globing;
unsigned int count;
} programs;
struct {
Eina_List *globing;
} callbacks;
} u;
};
/*----------*/
struct _Edje_Part_Collection
@ -841,6 +860,15 @@ struct _Edje_Part_Collection
Embryo_Program *script; /* all the embryo script code for this group */
const char *part;
/* *** generated at runtime *** */
struct {
Edje_Signals_Sources_Patterns programs;
Edje_Program **table_programs;
int table_programs_size;
} patterns;
/* *** *** */
unsigned char script_only;
unsigned char lua_script_only;
@ -1162,27 +1190,6 @@ struct _Edje_Signal_Source_Char
Eina_Array list;
};
struct _Edje_Signals_Sources_Patterns
{
Edje_Patterns *signals_patterns;
Edje_Patterns *sources_patterns;
Eina_Rbtree *exact_match;
union {
struct {
Edje_Program **globing;
unsigned int count;
} programs;
struct {
Eina_List *globing;
} callbacks;
} u;
};
typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns;
struct _Edje
{
Evas_Object_Smart_Clipped_Data *base;
@ -1209,14 +1216,12 @@ struct _Edje
Edje_Var_Pool *var_pool;
/* for faster lookups to avoid nth list walks */
Edje_Real_Part **table_parts;
Edje_Program **table_programs;
Edje_Real_Part *focused_part;
Eina_List *subobjs;
Eina_List *text_insert_filter_callbacks;
Eina_List *markup_filter_callbacks;
void *script_only_data;
int table_programs_size;
unsigned int table_parts_size;
Eina_List *groups;
@ -1230,7 +1235,6 @@ struct _Edje
struct {
Edje_Signals_Sources_Patterns callbacks;
Edje_Signals_Sources_Patterns programs;
} patterns;
int references;
@ -1896,8 +1900,8 @@ void _edje_unref(Edje *ed);
Eina_Bool _edje_program_run_iterate(Edje_Running_Program *runp, double tim);
void _edje_program_end(Edje *ed, Edje_Running_Program *runp);
void _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, const char *ssrc);
void _edje_programs_patterns_clean(Edje *ed);
void _edje_programs_patterns_init(Edje *ed);
void _edje_programs_patterns_clean(Edje_Part_Collection *ed);
void _edje_programs_patterns_init(Edje_Part_Collection *ed);
void _edje_emit(Edje *ed, const char *sig, const char *src);
void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *));
void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop);

View File

@ -463,7 +463,7 @@ _edje_program_run_iterate(Edje_Running_Program *runp, double tim)
if (pa->id >= 0)
{
pr = ed->table_programs[pa->id % ed->table_programs_size];
pr = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
if (pr) _edje_program_run(ed, pr, 0, "", "");
if (_edje_block_break(ed))
{
@ -709,7 +709,7 @@ _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig,
{
if (pa->id >= 0)
{
pr2 = ed->table_programs[pa->id % ed->table_programs_size];
pr2 = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
if (pr2) _edje_program_run(ed, pr2, 0, "", "");
if (_edje_block_break(ed)) goto break_prog;
}
@ -1049,7 +1049,7 @@ _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig,
{
if (pa->id >= 0)
{
pr2 = ed->table_programs[pa->id % ed->table_programs_size];
pr2 = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
if (pr2) _edje_program_run(ed, pr2, 0, "", "");
if (_edje_block_break(ed)) goto break_prog;
}
@ -1401,7 +1401,7 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src,
data.source = src;
data.matches = NULL;
if (ed->table_programs_size > 0)
if (ed->collection->patterns.table_programs_size > 0)
{
const Eina_Array *match;
#ifdef EDJE_PROGRAM_CACHE
@ -1411,19 +1411,19 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src,
Eina_Array_Iterator iterator;
unsigned int i;
if (ed->patterns.programs.u.programs.globing)
if (edje_match_programs_exec(ed->patterns.programs.signals_patterns,
ed->patterns.programs.sources_patterns,
if (ed->collection->patterns.programs.u.programs.globing)
if (edje_match_programs_exec(ed->collection->patterns.programs.signals_patterns,
ed->collection->patterns.programs.sources_patterns,
sig,
src,
ed->patterns.programs.u.programs.globing,
ed->collection->patterns.programs.u.programs.globing,
_edje_glob_callback,
&data,
prop) == 0)
goto break_prog;
match = edje_match_signal_source_hash_get(sig, src,
ed->patterns.programs.exact_match);
ed->collection->patterns.programs.exact_match);
if (match)
EINA_ARRAY_ITER_NEXT(match, i, pr, iterator)
_edje_glob_callback(pr, &data);