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
+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
- 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
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;
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;
}
/* 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)
{
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;
}
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;
}
//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;
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;
//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;
}
_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);
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)
_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;
}
_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;
}
/* 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));
{
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);
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)
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;
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, "", "");
}
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
}
}
- _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);
_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);
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)
{
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);
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
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
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;
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;
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;
struct {
Edje_Signals_Sources_Patterns callbacks;
- Edje_Signals_Sources_Patterns programs;
} patterns;
int references;
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);
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))
{
{
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;
}
{
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;
}
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
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);