edje: handle reallocation of pointed data properly for limits.
authorCedric Bail <cedric.bail@samsung.com>
Tue, 15 Oct 2013 09:15:07 +0000 (18:15 +0900)
committerCedric Bail <cedric.bail@samsung.com>
Tue, 15 Oct 2013 09:15:51 +0000 (18:15 +0900)
src/bin/edje/edje_cc.h
src/bin/edje/edje_cc_handlers.c
src/bin/edje/edje_cc_out.c

index cfb6271..f1c9367 100644 (file)
@@ -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);
index dc9a024..0c1e5ca 100644 (file)
@@ -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
      }
 }
 
index 889d9a0..575d3aa 100644 (file)
@@ -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
+_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((uintptr_t) &a->pc, sizeof (void*)) ^
+          eina_hash_int64((uintptr_t) &a->mem.dest, sizeof (void*));
+#else
+        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
-_double_pointer_key_hash(const void *key, int key_length EINA_UNUSED)
+_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(key, sizeof (void*)) ^
-     eina_hash_int64((void*)(((unsigned char*) key) + sizeof (void*)), sizeof (void*));
+        return 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->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->key);
+   list = eina_list_prepend(list, pl);
+   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->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
@@ -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;
+
+   key.pc = NULL;
+   key.mem.dest = src;
+   key.stable = EINA_TRUE;
 
-   list = eina_hash_find(part_dest_lookup, &src);
+   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);
                }
           }