From 4be4076cd427ba1754819d737421c49b638b8d3c Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Tue, 15 Oct 2013 18:15:07 +0900 Subject: [PATCH] edje: handle reallocation of pointed data properly for limits. --- src/bin/edje/edje_cc.h | 2 + src/bin/edje/edje_cc_handlers.c | 22 +-- src/bin/edje/edje_cc_out.c | 247 +++++++++++++++++++++++++++----- 3 files changed, 217 insertions(+), 54 deletions(-) diff --git a/src/bin/edje/edje_cc.h b/src/bin/edje/edje_cc.h index cfb6271de6..f1c9367fa3 100644 --- a/src/bin/edje/edje_cc.h +++ b/src/bin/edje/edje_cc.h @@ -152,6 +152,8 @@ void data_write(void); void data_queue_face_group_lookup(const char *name); void data_queue_group_lookup(const char *name, Edje_Part *part); void data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest); +void data_queue_part_reallocated_lookup(Edje_Part_Collection *pc, const char *name, + unsigned char **base, int offset); void data_queue_copied_part_lookup(Edje_Part_Collection *pc, int *src, int *dest); void data_queue_program_lookup(Edje_Part_Collection *pc, const char *name, int *dest); void data_queue_copied_program_lookup(Edje_Part_Collection *pc, int *src, int *dest); diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c index dc9a024eb4..0c1e5cafc0 100644 --- a/src/bin/edje/edje_cc_handlers.c +++ b/src/bin/edje/edje_cc_handlers.c @@ -2787,6 +2787,8 @@ st_collections_group_inherit(void) pcp2 = (Edje_Part_Collection_Parser *)pc2; pcp->default_mouse_events = pcp2->default_mouse_events; + // FIXME: Handle limits dup + #define STRDUP(x) x ? strdup(x) : NULL for (i = 0 ; i < pc2->parts_count ; i++) { @@ -5507,21 +5509,11 @@ st_collections_group_parts_part_description_limit(void) pc = eina_list_data_get(eina_list_last(edje_collections)); count = pc->limits.parts_count++; - // XXX: the data_queue_part_lookup uses a pointer TO the - // int id to fill in with the name in the parts[] array - // BUT... we REALLOC it.. which means this memory can - // be reloacted on realloc... so the lookups are invalid. - // - // as a QUICK fix this will just over-allocate a big big blob - // so we can queue a lot of limit lookups -// OLD code.... fix sometime -// pc->limits.parts = realloc(pc->limits.parts, -// pc->limits.parts_count * sizeof (Edje_Part_Limit)); -// temporary over-alloc of 128 slots to fix realloc + lookup bug - if (!pc->limits.parts) - pc->limits.parts = malloc(128 * sizeof (Edje_Part_Limit)); - data_queue_part_lookup(pc, current_part->name, - &(pc->limits.parts[count].part)); + pc->limits.parts = realloc(pc->limits.parts, + pc->limits.parts_count * sizeof (Edje_Part_Limit)); + data_queue_part_reallocated_lookup(pc, current_part->name, + (unsigned char**) &(pc->limits.parts), + (unsigned char*) &pc->limits.parts[count].part - (unsigned char*) pc->limits.parts); //fixme } } diff --git a/src/bin/edje/edje_cc_out.c b/src/bin/edje/edje_cc_out.c index 889d9a062d..575d3aafa7 100644 --- a/src/bin/edje/edje_cc_out.c +++ b/src/bin/edje/edje_cc_out.c @@ -27,6 +27,7 @@ typedef struct _External_Lookup External_Lookup; typedef struct _Part_Lookup Part_Lookup; +typedef struct _Part_Lookup_Key Part_Lookup_Key; typedef struct _Program_Lookup Program_Lookup; typedef struct _Group_Lookup Group_Lookup; typedef struct _Image_Lookup Image_Lookup; @@ -39,11 +40,25 @@ struct _External_Lookup char *name; }; -struct _Part_Lookup +struct _Part_Lookup_Key { Edje_Part_Collection *pc; + + union { + int *dest; + struct { + unsigned char **base; + int offset; + } reallocated; + } mem; + + Eina_Bool stable : 1; +}; + +struct _Part_Lookup +{ + Part_Lookup_Key key; char *name; - int *dest; }; struct _Program_Lookup @@ -201,28 +216,96 @@ error_and_abort(Eet_File *ef EINA_UNUSED, const char *fmt, ...) } static unsigned int -_double_pointer_key_length(const void *key EINA_UNUSED) +_part_lookup_key_length(const void *key EINA_UNUSED) { - return sizeof (void*) * 2; + return sizeof (Part_Lookup_Key); } static int -_double_pointer_key_cmp(const void *key1, int key1_length, +_part_lookup_key_pc_cmp(const void *key1, int key1_length EINA_UNUSED, const void *key2, int key2_length EINA_UNUSED) { - return memcmp(key1, key2, key1_length); + const Part_Lookup_Key *a = key1; + const Part_Lookup_Key *b = key2; + uintptr_t delta; + + delta = a->pc - b->pc; + if (delta) return delta; + + if (a->stable) return a->mem.dest - b->mem.dest; + + delta = a->mem.reallocated.base - b->mem.reallocated.base; + if (delta) return delta; + return a->mem.reallocated.offset - b->mem.reallocated.offset; } static int -_double_pointer_key_hash(const void *key, int key_length EINA_UNUSED) +_part_lookup_key_pc_hash(const void *key, int key_length EINA_UNUSED) { + const Part_Lookup_Key *a = key; + + if (a->stable) + { #ifdef __LP64__ - return eina_hash_int64(key, sizeof (void*)) ^ - eina_hash_int64((void*)(((unsigned char*) key) + sizeof (void*)), sizeof (void*)); + return eina_hash_int64((uintptr_t) &a->pc, sizeof (void*)) ^ + eina_hash_int64((uintptr_t) &a->mem.dest, sizeof (void*)); #else - /* double 32 bits pointer is ... 64bits awesome ! */ - return eina_hash_int64(key, key_length); + return eina_hash_int32((uintptr_t*) &a->pc, sizeof (void*)) ^ + eina_hash_int32((uintptr_t*) &a->mem.dest, sizeof (void*)); #endif + } + else + { +#ifdef __LP64__ + return eina_hash_int64((uintptr_t *) &a->pc, sizeof (void*)) ^ + eina_hash_int64((uintptr_t *) &a->mem.reallocated.base, sizeof (void*)) ^ + eina_hash_int32((unsigned int *) &a->mem.reallocated.offset, sizeof (int)); +#else + return eina_hash_int32((uintptr_t *) &a->pc, sizeof (void*)) ^ + eina_hash_int32((uintptr_t *) &a->mem.reallocated.base, sizeof (void*)) ^ + eina_hash_int32((unsigned int *) &a->mem.reallocated.offset, sizeof (int)); +#endif + } +} + +static int +_part_lookup_key_cmp(const void *key1, int key1_length EINA_UNUSED, + const void *key2, int key2_length EINA_UNUSED) +{ + const Part_Lookup_Key *a = key1; + const Part_Lookup_Key *b = key2; + uintptr_t delta; + + if (a->stable) return a->mem.dest - b->mem.dest; + + delta = a->mem.reallocated.base - b->mem.reallocated.base; + if (delta) return delta; + return a->mem.reallocated.offset - b->mem.reallocated.offset; +} + +static int +_part_lookup_key_hash(const void *key, int key_length EINA_UNUSED) +{ + const Part_Lookup_Key *a = key; + + if (a->stable) + { +#ifdef __LP64__ + return eina_hash_int64((uintptr_t *) &a->mem.dest, sizeof (void*)); +#else + return eina_hash_int32((uintptr_t *) &a->mem.dest, sizeof (void*)); +#endif + } + else + { +#ifdef __LP64__ + return eina_hash_int64((uintptr_t *) &a->mem.reallocated.base, sizeof (void*)) ^ + eina_hash_int32((unsigned int *) &a->mem.reallocated.offset, sizeof (int)); +#else + return eina_hash_int32((uintptr_t *) &a->mem.reallocated.base, sizeof (void*)) ^ + eina_hash_int32((unsigned int *) &a->mem.reallocated.offset, sizeof (int)); +#endif + } } static void @@ -238,10 +321,14 @@ data_setup(void) edd_edje_file = _edje_edd_edje_file; edd_edje_part_collection = _edje_edd_edje_part_collection; - part_dest_lookup = eina_hash_pointer_new(EINA_FREE_CB(eina_list_free)); - part_pc_dest_lookup = eina_hash_new(EINA_KEY_LENGTH(_double_pointer_key_length), - EINA_KEY_CMP(_double_pointer_key_cmp), - EINA_KEY_HASH(_double_pointer_key_hash), + part_dest_lookup = eina_hash_new(EINA_KEY_LENGTH(_part_lookup_key_length), + EINA_KEY_CMP(_part_lookup_key_cmp), + EINA_KEY_HASH(_part_lookup_key_hash), + EINA_FREE_CB(eina_list_free), + 8); + part_pc_dest_lookup = eina_hash_new(EINA_KEY_LENGTH(_part_lookup_key_length), + EINA_KEY_CMP(_part_lookup_key_pc_cmp), + EINA_KEY_HASH(_part_lookup_key_pc_hash), EINA_FREE_CB(data_part_lookup_free), 8); } @@ -1812,12 +1899,13 @@ data_queue_face_group_lookup(const char *name) void data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest) { - void *key[2]; + Part_Lookup_Key key; Part_Lookup *pl = NULL; Eina_List *list; - key[0] = pc; - key[1] = dest; + key.pc = pc; + key.mem.dest = dest; + key.stable = EINA_TRUE; pl = eina_hash_find(part_pc_dest_lookup, &key); if (pl) @@ -1829,9 +1917,9 @@ data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest) } else { - list = eina_hash_find(part_dest_lookup, &pl->dest); + list = eina_hash_find(part_dest_lookup, &pl->key); list = eina_list_remove(list, pl); - eina_hash_set(part_dest_lookup, &pl->dest, list); + eina_hash_set(part_dest_lookup, &pl->key, list); eina_hash_del(part_pc_dest_lookup, &key, pl); } return; @@ -1840,15 +1928,63 @@ data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest) if (!name[0]) return; pl = mem_alloc(SZ(Part_Lookup)); - pl->pc = pc; pl->name = mem_strdup(name); - pl->dest = dest; + pl->key.pc = pc; + pl->key.mem.dest = dest; + pl->key.stable = EINA_TRUE; eina_hash_add(part_pc_dest_lookup, &key, pl); - list = eina_hash_find(part_dest_lookup, &pl->dest); + list = eina_hash_find(part_dest_lookup, &pl->key); list = eina_list_prepend(list, pl); - eina_hash_set(part_dest_lookup, &pl->dest, list); + eina_hash_set(part_dest_lookup, &pl->key, list); +} + +void +data_queue_part_reallocated_lookup(Edje_Part_Collection *pc, const char *name, + unsigned char **base, int offset) +{ + Part_Lookup_Key key; + Part_Lookup *pl = NULL; + Eina_List *list; + + key.pc = pc; + key.mem.reallocated.base = base; + key.mem.reallocated.offset = offset; + key.stable = EINA_FALSE; + + pl = eina_hash_find(part_pc_dest_lookup, &key); + if (pl) + { + if (name[0]) + { + free(pl->name); + pl->name = mem_strdup(name); + } + else + { + list = eina_hash_find(part_dest_lookup, &pl->key); + list = eina_list_remove(list, pl); + eina_hash_set(part_dest_lookup, &pl->key, list); + eina_hash_del(part_pc_dest_lookup, &key, pl); + } + return; + } + + if (!name[0]) return; + + pl = mem_alloc(SZ(Part_Lookup)); + pl->name = mem_strdup(name); + pl->key.pc = pc; + pl->key.mem.reallocated.base = base; + pl->key.mem.reallocated.offset = offset; + pl->key.stable = EINA_FALSE; + + eina_hash_add(part_pc_dest_lookup, &key, pl); + + list = eina_hash_find(part_dest_lookup, &pl->key); + list = eina_list_prepend(list, pl); + eina_hash_set(part_dest_lookup, &pl->key, list); } void @@ -1857,21 +1993,27 @@ data_queue_copied_part_lookup(Edje_Part_Collection *pc, int *src, int *dest) Eina_List *list; Eina_List *l; Part_Lookup *pl; + Part_Lookup_Key key; - list = eina_hash_find(part_dest_lookup, &src); + key.pc = NULL; + key.mem.dest = src; + key.stable = EINA_TRUE; + + list = eina_hash_find(part_dest_lookup, &key); EINA_LIST_FOREACH(list, l, pl) - data_queue_part_lookup(pc, pl->name, dest); + if (pl->key.stable) + data_queue_part_lookup(pc, pl->name, dest); } void data_queue_anonymous_lookup(Edje_Part_Collection *pc, Edje_Program *ep, int *dest) { - Eina_List *l, *l2; + Eina_List *l, *l1, *l2, *l3; Program_Lookup *pl; if (!ep) return; /* FIXME: should we stop compiling ? */ - EINA_LIST_FOREACH(program_lookups, l, pl) + EINA_LIST_FOREACH_SAFE(program_lookups, l, l1, pl) { if (pl->u.ep == ep) { @@ -1880,16 +2022,16 @@ data_queue_anonymous_lookup(Edje_Part_Collection *pc, Edje_Program *ep, int *des cd = eina_list_data_get(eina_list_last(codes)); - EINA_LIST_FOREACH(cd->programs, l2, cp) + EINA_LIST_FOREACH_SAFE(cd->programs, l2, l3, cp) { if (&(cp->id) == pl->dest) { - cd->programs = eina_list_remove(cd->programs, cp); + cd->programs = eina_list_remove_list(cd->programs, l2); free(cp); cp = NULL; } } - program_lookups = eina_list_remove(program_lookups, pl); + program_lookups = eina_list_remove_list(program_lookups, l); free(pl); } } @@ -2053,6 +2195,20 @@ handle_slave_lookup(Eina_List *list, int *master, int value) *sl->slave = value; } +static void +data_process_part_set(Part_Lookup *target, int value) +{ + if (target->key.stable) + { + *(target->key.mem.dest) = value; + } + else + { + *((int*)(*target->key.mem.reallocated.base + + target->key.mem.reallocated.offset)) = value; + } +} + void data_process_lookups(void) { @@ -2149,30 +2305,43 @@ data_process_lookups(void) if (!strcmp(part->name, "-")) { - *(part->dest) = -1; + data_process_part_set(part, -1); } else { char *alias; - alias = eina_hash_find(part->pc->alias, part->name); + alias = eina_hash_find(part->key.pc->alias, part->name); if (!alias) alias = part->name; - for (i = 0; i < part->pc->parts_count; ++i) + for (i = 0; i < part->key.pc->parts_count; ++i) { - ep = part->pc->parts[i]; + ep = part->key.pc->parts[i]; if ((ep->name) && (!strcmp(ep->name, alias))) { - handle_slave_lookup(part_slave_lookups, part->dest, ep->id); - *(part->dest) = ep->id; + int *master; + + if (part->key.stable) + { + master = part->key.mem.dest; + } + else + { + master = (int*)(*part->key.mem.reallocated.base + + part->key.mem.reallocated.offset); + } + handle_slave_lookup(part_slave_lookups, + master, + ep->id); + data_process_part_set(part, ep->id); break; } } - if (i == part->pc->parts_count) + if (i == part->key.pc->parts_count) { ERR("Unable to find part name \"%s\" needed in group '%s'.", - alias, part->pc->part); + alias, part->key.pc->part); exit(-1); } }