YaGL: Replace AVL trees with hashes 04/12904/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 25 Nov 2013 14:53:49 +0000 (18:53 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 25 Nov 2013 14:53:49 +0000 (18:53 +0400)
The number of OpenGL objects and/or shader
program locations can be really large in
case of heavy graphics applications, so object
lookup time matters. Using hash tables is more
appropriate since they have much less lookup
time. The difference can be seen when running
Doom3, AVL lookup function was hot in perf report

Change-Id: I46121ecd8d8c0d392fe6f3aa4aba0c96a90280ae

hw/yagl/Makefile.objs
hw/yagl/yagl_apis/gles/yagl_gles_api_ps.c
hw/yagl/yagl_apis/gles/yagl_gles_api_ps.h
hw/yagl/yagl_avl.c [deleted file]
hw/yagl/yagl_avl.h [deleted file]
hw/yagl/yagl_object_map.c
hw/yagl/yagl_object_map.h

index 39434fc1ccb6a721f8a8830a3b4c346bb2a7eb10..2453ae9f4fa56a66af9eec3e18e33c93345b5a1b 100644 (file)
@@ -12,7 +12,6 @@ obj-y += yagl_handle_gen.o
 obj-y += yagl_dyn_lib.o
 obj-y += yagl_api.o
 obj-y += yagl_vector.o
-obj-y += yagl_avl.o
 obj-y += yagl_transport.o
 obj-y += yagl_egl_backend.o
 obj-y += yagl_eglb_display.o
index 7af362253f9056d603660abf48621e590e01add6..2f2245fdbfec75e37fd4465334e907debcd65d6f 100644 (file)
 #include "yagl_gles_api_ps.h"
 #include "yagl_process.h"
 #include "yagl_thread.h"
-#include "yagl_avl.h"
-
-struct yagl_location
-{
-    uint32_t location;
-
-    GLint actual_location;
-};
-
-static int yagl_location_compare(const void *avl_a,
-                                 const void *avl_b,
-                                 void *avl_param)
-{
-    const struct yagl_location *a = avl_a;
-    const struct yagl_location *b = avl_b;
-
-    if (a->location < b->location) {
-        return -1;
-    } else if (a->location > b->location) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static void yagl_location_destroy(void *avl_item, void *avl_param)
-{
-    g_free(avl_item);
-}
 
 void yagl_gles_api_ps_init(struct yagl_gles_api_ps *gles_api_ps,
                            struct yagl_gles_driver *driver)
 {
     gles_api_ps->driver = driver;
-    gles_api_ps->locations = yagl_avl_create(&yagl_location_compare,
-                                             NULL,
-                                             NULL);
+    gles_api_ps->locations = g_hash_table_new_full(g_direct_hash,
+                                                   g_direct_equal,
+                                                   NULL,
+                                                   NULL);
+
     assert(gles_api_ps->locations);
 }
 
 void yagl_gles_api_ps_cleanup(struct yagl_gles_api_ps *gles_api_ps)
 {
-    yagl_avl_destroy(gles_api_ps->locations, &yagl_location_destroy);
+    g_hash_table_destroy(gles_api_ps->locations);
 }
 
 void yagl_gles_api_ps_add_location(struct yagl_gles_api_ps *gles_api_ps,
                                    uint32_t location,
                                    GLint actual_location)
 {
-    struct yagl_location *item = g_malloc0(sizeof(struct yagl_location));
+    guint size = g_hash_table_size(gles_api_ps->locations);
 
-    item->location = location;
-    item->actual_location = actual_location;
+    g_hash_table_insert(gles_api_ps->locations,
+                        GUINT_TO_POINTER(location),
+                        GINT_TO_POINTER(actual_location));
 
-    yagl_avl_assert_insert(gles_api_ps->locations, item);
+    assert(g_hash_table_size(gles_api_ps->locations) > size);
 }
 
 GLint yagl_gles_api_ps_translate_location(struct yagl_gles_api_ps *gles_api_ps,
                                           GLboolean tl,
                                           uint32_t location)
 {
-    struct yagl_location *item;
-    struct yagl_location dummy;
+    gpointer key, item;
 
     if (!tl) {
         return location;
     }
 
-    dummy.location = location;
-
-    item = yagl_avl_find(gles_api_ps->locations, &dummy);
-
-    if (item) {
-        return item->actual_location;
+    if (g_hash_table_lookup_extended(gles_api_ps->locations,
+                                     GUINT_TO_POINTER(location),
+                                     &key,
+                                     &item))
+    {
+        return GPOINTER_TO_INT(item);
     } else {
         assert(0);
         return -1;
@@ -114,12 +87,9 @@ GLint yagl_gles_api_ps_translate_location(struct yagl_gles_api_ps *gles_api_ps,
 void yagl_gles_api_ps_remove_location(struct yagl_gles_api_ps *gles_api_ps,
                                       uint32_t location)
 {
-    void *item;
-    struct yagl_location dummy;
-
-    dummy.location = location;
+    guint size = g_hash_table_size(gles_api_ps->locations);
 
-    item = yagl_avl_assert_delete(gles_api_ps->locations, &dummy);
+    g_hash_table_remove(gles_api_ps->locations, GUINT_TO_POINTER(location));
 
-    yagl_location_destroy(item, gles_api_ps->locations->avl_param);
+    assert(g_hash_table_size(gles_api_ps->locations) < size);
 }
index 50ac2bbe4a5f050b31e1672bf8ae49e828a9e765..f5716b312b6c329983429165241bdb498d39308c 100644 (file)
@@ -31,9 +31,9 @@
 #define _QEMU_YAGL_GLES_API_PS_H
 
 #include "yagl_api.h"
+#include <glib.h>
 
 struct yagl_gles_driver;
-struct yagl_avl_table;
 
 struct yagl_gles_api_ps
 {
@@ -41,7 +41,7 @@ struct yagl_gles_api_ps
 
     struct yagl_gles_driver *driver;
 
-    struct yagl_avl_table *locations;
+    GHashTable *locations;
 };
 
 void yagl_gles_api_ps_init(struct yagl_gles_api_ps *gles_api_ps,
diff --git a/hw/yagl/yagl_avl.c b/hw/yagl/yagl_avl.c
deleted file mode 100644 (file)
index 0c19a3a..0000000
+++ /dev/null
@@ -1,873 +0,0 @@
-/*
- * yagl
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * Stanislav Vorobiov <s.vorobiov@samsung.com>
- * Jinhyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-/*
- * AVL tree implementation from libavl project.
- */
-
-#include "yagl_avl.h"
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * Creates and returns a new table
- * with comparison function |compare| using parameter |param|
- * and memory allocator |allocator|.
- * Returns |NULL| if memory allocation failed.
- */
-struct yagl_avl_table *yagl_avl_create(yagl_avl_comparison_func *compare,
-    void *param,
-    struct yagl_libavl_allocator *allocator)
-{
-    struct yagl_avl_table *tree;
-
-    assert(compare != NULL);
-
-    if (allocator == NULL) {
-        allocator = &yagl_avl_allocator_default;
-    }
-
-    tree = allocator->libavl_malloc(allocator, sizeof(*tree));
-    if (tree == NULL) {
-        return NULL;
-    }
-
-    tree->avl_root = NULL;
-    tree->avl_compare = compare;
-    tree->avl_param = param;
-    tree->avl_alloc = allocator;
-    tree->avl_count = 0;
-    tree->avl_generation = 0;
-
-    return tree;
-}
-
-/*
- * Search |tree| for an item matching |item|, and return it if found.
- * Otherwise return |NULL|.
- */
-void *yagl_avl_find(const struct yagl_avl_table *tree, const void *item)
-{
-    const struct yagl_avl_node *p;
-
-    assert(tree != NULL && item != NULL);
-    for (p = tree->avl_root; p != NULL;) {
-        int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
-
-        if (cmp < 0) {
-            p = p->avl_link[0];
-        } else if (cmp > 0) {
-            p = p->avl_link[1];
-        } else {
-            return p->avl_data;
-        }
-    }
-
-    return NULL;
-}
-
-/*
- * Inserts |item| into |tree| and returns a pointer to |item|'s address.
- * If a duplicate item is found in the tree,
- * returns a pointer to the duplicate without inserting |item|.
- * Returns |NULL| in case of memory allocation failure.
- */
-void **yagl_avl_probe(struct yagl_avl_table *tree, void *item)
-{
-    struct yagl_avl_node *y, *z; /* Top node to update balance factor, and parent. */
-    struct yagl_avl_node *p, *q; /* Iterator, and parent. */
-    struct yagl_avl_node *n; /* Newly inserted node. */
-    struct yagl_avl_node *w; /* New root of rebalanced subtree. */
-    int dir; /* Direction to descend. */
-
-    unsigned char da[YAGL_AVL_MAX_HEIGHT]; /* Cached comparison results. */
-    int k = 0; /* Number of cached results. */
-
-    assert(tree != NULL && item != NULL);
-
-    z = (struct yagl_avl_node *) &tree->avl_root;
-    y = tree->avl_root;
-    dir = 0;
-    for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir]) {
-        int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
-        if (cmp == 0) {
-            return &p->avl_data;
-        }
-
-        if (p->avl_balance != 0) {
-            z = q, y = p, k = 0;
-        }
-        da[k++] = dir = cmp > 0;
-    }
-
-    n = q->avl_link[dir] = tree->avl_alloc->libavl_malloc(tree->avl_alloc,
-        sizeof(*n));
-    if (n == NULL) {
-        return NULL;
-    }
-
-    tree->avl_count++;
-    n->avl_data = item;
-    n->avl_link[0] = n->avl_link[1] = NULL;
-    n->avl_balance = 0;
-    if (y == NULL) {
-        return &n->avl_data;
-    }
-
-    for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++) {
-        if (da[k] == 0) {
-            p->avl_balance--;
-        } else {
-            p->avl_balance++;
-        }
-    }
-
-    if (y->avl_balance == -2) {
-        struct yagl_avl_node *x = y->avl_link[0];
-        if (x->avl_balance == -1) {
-            w = x;
-            y->avl_link[0] = x->avl_link[1];
-            x->avl_link[1] = y;
-            x->avl_balance = y->avl_balance = 0;
-        } else {
-            assert(x->avl_balance == 1);
-            w = x->avl_link[1];
-            x->avl_link[1] = w->avl_link[0];
-            w->avl_link[0] = x;
-            y->avl_link[0] = w->avl_link[1];
-            w->avl_link[1] = y;
-            if (w->avl_balance == -1) {
-                x->avl_balance = 0, y->avl_balance = 1;
-            } else if (w->avl_balance == 0) {
-                x->avl_balance = y->avl_balance = 0;
-            } else {
-                x->avl_balance = -1, y->avl_balance = 0;
-            }
-            w->avl_balance = 0;
-        }
-    } else if (y->avl_balance == 2) {
-        struct yagl_avl_node *x = y->avl_link[1];
-        if (x->avl_balance == 1) {
-            w = x;
-            y->avl_link[1] = x->avl_link[0];
-            x->avl_link[0] = y;
-            x->avl_balance = y->avl_balance = 0;
-        } else {
-            assert(x->avl_balance == -1);
-            w = x->avl_link[0];
-            x->avl_link[0] = w->avl_link[1];
-            w->avl_link[1] = x;
-            y->avl_link[1] = w->avl_link[0];
-            w->avl_link[0] = y;
-            if (w->avl_balance == 1) {
-                x->avl_balance = 0, y->avl_balance = -1;
-            } else if (w->avl_balance == 0) {
-                x->avl_balance = y->avl_balance = 0;
-            } else {
-                x->avl_balance = 1, y->avl_balance = 0;
-            }
-            w->avl_balance = 0;
-        }
-    } else {
-        return &n->avl_data;
-    }
-    z->avl_link[y != z->avl_link[0]] = w;
-
-    tree->avl_generation++;
-    return &n->avl_data;
-}
-
-/*
- * Inserts |item| into |table|.
- * Returns |NULL| if |item| was successfully inserted
- * or if a memory allocation error occurred.
- * Otherwise, returns the duplicate item.
- */
-void *yagl_avl_insert(struct yagl_avl_table *table, void *item)
-{
-    void **p = yagl_avl_probe(table, item);
-    return p == NULL || *p == item ? NULL : *p;
-}
-
-/*
- * Inserts |item| into |table|, replacing any duplicate item.
- * Returns |NULL| if |item| was inserted without replacing a duplicate,
- * or if a memory allocation error occurred.
- * Otherwise, returns the item that was replaced.
- */
-void *yagl_avl_replace(struct yagl_avl_table *table, void *item)
-{
-    void **p = yagl_avl_probe(table, item);
-    if (p == NULL || *p == item) {
-        return NULL;
-    } else {
-        void *r = *p;
-        *p = item;
-        return r;
-    }
-}
-
-/*
- * Deletes from |tree| and returns an item matching |item|.
- * Returns a null pointer if no matching item found.
- */
-void *yagl_avl_delete(struct yagl_avl_table *tree, const void *item)
-{
-    /* Stack of nodes. */
-    struct yagl_avl_node *pa[YAGL_AVL_MAX_HEIGHT]; /* Nodes. */
-    unsigned char da[YAGL_AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
-    int k; /* Stack pointer. */
-
-    struct yagl_avl_node *p; /* Traverses tree to find node to delete. */
-    int cmp; /* Result of comparison between |item| and |p|. */
-
-    assert(tree != NULL && item != NULL);
-
-    k = 0;
-    p = (struct yagl_avl_node *) &tree->avl_root;
-    for (cmp = -1; cmp != 0;
-        cmp = tree->avl_compare(item, p->avl_data, tree->avl_param)) {
-        int dir = cmp > 0;
-
-        pa[k] = p;
-        da[k++] = dir;
-
-        p = p->avl_link[dir];
-        if (p == NULL) {
-            return NULL;
-        }
-    }
-    item = p->avl_data;
-
-    if (p->avl_link[1] == NULL) {
-        pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
-    } else {
-        struct yagl_avl_node *r = p->avl_link[1];
-        if (r->avl_link[0] == NULL) {
-            r->avl_link[0] = p->avl_link[0];
-            r->avl_balance = p->avl_balance;
-            pa[k - 1]->avl_link[da[k - 1]] = r;
-            da[k] = 1;
-            pa[k++] = r;
-        } else {
-            struct yagl_avl_node *s;
-            int j = k++;
-
-            for (;;) {
-                da[k] = 0;
-                pa[k++] = r;
-                s = r->avl_link[0];
-                if (s->avl_link[0] == NULL) {
-                    break;
-                }
-
-                r = s;
-            }
-
-            s->avl_link[0] = p->avl_link[0];
-            r->avl_link[0] = s->avl_link[1];
-            s->avl_link[1] = p->avl_link[1];
-            s->avl_balance = p->avl_balance;
-
-            pa[j - 1]->avl_link[da[j - 1]] = s;
-            da[j] = 1;
-            pa[j] = s;
-        }
-    }
-
-    tree->avl_alloc->libavl_free(tree->avl_alloc, p);
-
-    assert(k > 0);
-    while (--k > 0) {
-        struct yagl_avl_node *y = pa[k];
-
-        if (da[k] == 0) {
-            y->avl_balance++;
-            if (y->avl_balance == 1) {
-                break;
-            } else if (y->avl_balance == 2) {
-                struct yagl_avl_node *x = y->avl_link[1];
-                if (x->avl_balance == -1) {
-                    struct yagl_avl_node *w;
-                    assert(x->avl_balance == -1);
-                    w = x->avl_link[0];
-                    x->avl_link[0] = w->avl_link[1];
-                    w->avl_link[1] = x;
-                    y->avl_link[1] = w->avl_link[0];
-                    w->avl_link[0] = y;
-                    if (w->avl_balance == 1) {
-                        x->avl_balance = 0, y->avl_balance = -1;
-                    } else if (w->avl_balance == 0) {
-                        x->avl_balance = y->avl_balance = 0;
-                    } else {
-                        x->avl_balance = 1, y->avl_balance = 0;
-                    }
-                    w->avl_balance = 0;
-                    pa[k - 1]->avl_link[da[k - 1]] = w;
-                } else {
-                    y->avl_link[1] = x->avl_link[0];
-                    x->avl_link[0] = y;
-                    pa[k - 1]->avl_link[da[k - 1]] = x;
-                    if (x->avl_balance == 0) {
-                        x->avl_balance = -1;
-                        y->avl_balance = 1;
-                        break;
-                    } else {
-                        x->avl_balance = y->avl_balance = 0;
-                    }
-                }
-            }
-        } else {
-            y->avl_balance--;
-            if (y->avl_balance == -1) {
-                break;
-            } else if (y->avl_balance == -2) {
-                struct yagl_avl_node *x = y->avl_link[0];
-                if (x->avl_balance == 1) {
-                    struct yagl_avl_node *w;
-                    assert(x->avl_balance == 1);
-                    w = x->avl_link[1];
-                    x->avl_link[1] = w->avl_link[0];
-                    w->avl_link[0] = x;
-                    y->avl_link[0] = w->avl_link[1];
-                    w->avl_link[1] = y;
-                    if (w->avl_balance == -1) {
-                        x->avl_balance = 0, y->avl_balance = 1;
-                    } else if (w->avl_balance == 0) {
-                        x->avl_balance = y->avl_balance = 0;
-                    } else {
-                        x->avl_balance = -1, y->avl_balance = 0;
-                    }
-                    w->avl_balance = 0;
-                    pa[k - 1]->avl_link[da[k - 1]] = w;
-                } else {
-                    y->avl_link[0] = x->avl_link[1];
-                    x->avl_link[1] = y;
-                    pa[k - 1]->avl_link[da[k - 1]] = x;
-                    if (x->avl_balance == 0) {
-                        x->avl_balance = 1;
-                        y->avl_balance = -1;
-                        break;
-                    } else {
-                        x->avl_balance = y->avl_balance = 0;
-                    }
-                }
-            }
-        }
-    }
-
-    tree->avl_count--;
-    tree->avl_generation++;
-    return (void *) item;
-}
-
-/*
- * Refreshes the stack of parent pointers in |trav|
- * and updates its generation number.
- */
-static void yagl_trav_refresh(struct yagl_avl_traverser *trav)
-{
-    assert(trav != NULL);
-
-    trav->avl_generation = trav->avl_table->avl_generation;
-
-    if (trav->avl_node != NULL) {
-        yagl_avl_comparison_func *cmp = trav->avl_table->avl_compare;
-        void *param = trav->avl_table->avl_param;
-        struct yagl_avl_node *node = trav->avl_node;
-        struct yagl_avl_node *i;
-
-        trav->avl_height = 0;
-        for (i = trav->avl_table->avl_root; i != node;) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            assert(i != NULL);
-
-            trav->avl_stack[trav->avl_height++] = i;
-            i = i->avl_link[cmp(node->avl_data, i->avl_data, param) > 0];
-        }
-    }
-}
-
-/*
- * Initializes |trav| for use with |tree|
- * and selects the null node.
- */
-void yagl_avl_t_init(struct yagl_avl_traverser *trav,
-                     struct yagl_avl_table *tree)
-{
-    trav->avl_table = tree;
-    trav->avl_node = NULL;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-}
-
-/*
- * Initializes |trav| for |tree|
- * and selects and returns a pointer to its least-valued item.
- * Returns |NULL| if |tree| contains no nodes.
- */
-void *yagl_avl_t_first(struct yagl_avl_traverser *trav,
-                       struct yagl_avl_table *tree)
-{
-    struct yagl_avl_node *x;
-
-    assert(tree != NULL && trav != NULL);
-
-    trav->avl_table = tree;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-
-    x = tree->avl_root;
-    if (x != NULL) {
-        while (x->avl_link[0] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[0];
-        }
-    }
-    trav->avl_node = x;
-
-    return x != NULL ? x->avl_data : NULL;
-}
-
-/*
- * Initializes |trav| for |tree|
- * and selects and returns a pointer to its greatest-valued item.
- * Returns |NULL| if |tree| contains no nodes.
- */
-void *yagl_avl_t_last(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree)
-{
-    struct yagl_avl_node *x;
-
-    assert(tree != NULL && trav != NULL);
-
-    trav->avl_table = tree;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-
-    x = tree->avl_root;
-    if (x != NULL) {
-        while (x->avl_link[1] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[1];
-        }
-    }
-    trav->avl_node = x;
-
-    return x != NULL ? x->avl_data : NULL;
-}
-
-/*
- * Searches for |item| in |tree|.
- * If found, initializes |trav| to the item found and returns the item
- * as well.
- * If there is no matching item, initializes |trav| to the null item
- * and returns |NULL|.
- */
-void *yagl_avl_t_find(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree, void *item)
-{
-    struct yagl_avl_node *p, *q;
-
-    assert(trav != NULL && tree != NULL && item != NULL);
-    trav->avl_table = tree;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-    for (p = tree->avl_root; p != NULL; p = q) {
-        int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
-
-        if (cmp < 0) {
-            q = p->avl_link[0];
-        } else if (cmp > 0) {
-            q = p->avl_link[1];
-        } else {
-            trav->avl_node = p;
-            return p->avl_data;
-        }
-
-        assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-        trav->avl_stack[trav->avl_height++] = p;
-    }
-
-    trav->avl_height = 0;
-    trav->avl_node = NULL;
-    return NULL;
-}
-
-/*
- * Attempts to insert |item| into |tree|.
- * If |item| is inserted successfully, it is returned and |trav| is
- * initialized to its location.
- * If a duplicate is found, it is returned and |trav| is initialized to
- * its location.  No replacement of the item occurs.
- * If a memory allocation failure occurs, |NULL| is returned and |trav|
- * is initialized to the null item.
- */
-void
-*yagl_avl_t_insert(struct yagl_avl_traverser *trav,
-                   struct yagl_avl_table *tree, void *item)
-{
-    void **p;
-
-    assert(trav != NULL && tree != NULL && item != NULL);
-
-    p = yagl_avl_probe(tree, item);
-    if (p != NULL) {
-        trav->avl_table = tree;
-        trav->avl_node = ((struct yagl_avl_node *) ((char *) p
-            - offsetof(struct yagl_avl_node, avl_data)));
-        trav->avl_generation = tree->avl_generation - 1;
-        return *p;
-    } else {
-        yagl_avl_t_init(trav, tree);
-        return NULL;
-    }
-}
-
-/* Initializes |trav| to have the same current node as |src|. */
-void *yagl_avl_t_copy(struct yagl_avl_traverser *trav,
-                      const struct yagl_avl_traverser *src)
-{
-    assert(trav != NULL && src != NULL);
-
-    if (trav != src) {
-        trav->avl_table = src->avl_table;
-        trav->avl_node = src->avl_node;
-        trav->avl_generation = src->avl_generation;
-        if (trav->avl_generation == trav->avl_table->avl_generation) {
-            trav->avl_height = src->avl_height;
-            memcpy(trav->avl_stack, (const void *) src->avl_stack,
-                sizeof(*trav->avl_stack) * trav->avl_height);
-        }
-    }
-
-    return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
-}
-
-/*
- * Returns the next data item in inorder
- * within the tree being traversed with |trav|,
- * or if there are no more data items returns |NULL|.
- */
-void *yagl_avl_t_next(struct yagl_avl_traverser *trav)
-{
-    struct yagl_avl_node *x;
-
-    assert(trav != NULL);
-
-    if (trav->avl_generation != trav->avl_table->avl_generation) {
-        yagl_trav_refresh(trav);
-    }
-
-    x = trav->avl_node;
-    if (x == NULL) {
-        return yagl_avl_t_first(trav, trav->avl_table);
-    } else if (x->avl_link[1] != NULL) {
-        assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-        trav->avl_stack[trav->avl_height++] = x;
-        x = x->avl_link[1];
-
-        while (x->avl_link[0] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[0];
-        }
-    } else {
-        struct yagl_avl_node *y;
-
-        do {
-            if (trav->avl_height == 0) {
-                trav->avl_node = NULL;
-                return NULL;
-            }
-
-            y = x;
-            x = trav->avl_stack[--trav->avl_height];
-        } while (y == x->avl_link[1]);
-    }
-    trav->avl_node = x;
-
-    return x->avl_data;
-}
-
-/*
- * Returns the previous data item in inorder
- * within the tree being traversed with |trav|,
- * or if there are no more data items returns |NULL|.
- */
-void *yagl_avl_t_prev(struct yagl_avl_traverser *trav)
-{
-    struct yagl_avl_node *x;
-
-    assert(trav != NULL);
-
-    if (trav->avl_generation != trav->avl_table->avl_generation) {
-        yagl_trav_refresh(trav);
-    }
-
-    x = trav->avl_node;
-    if (x == NULL) {
-        return yagl_avl_t_last(trav, trav->avl_table);
-    } else if (x->avl_link[0] != NULL) {
-        assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-        trav->avl_stack[trav->avl_height++] = x;
-        x = x->avl_link[0];
-
-        while (x->avl_link[1] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[1];
-        }
-    } else {
-        struct yagl_avl_node *y;
-
-        do {
-            if (trav->avl_height == 0) {
-                trav->avl_node = NULL;
-                return NULL;
-            }
-
-            y = x;
-            x = trav->avl_stack[--trav->avl_height];
-        } while (y == x->avl_link[0]);
-    }
-    trav->avl_node = x;
-
-    return x->avl_data;
-}
-
-/* Returns |trav|'s current item. */
-void *yagl_avl_t_cur(struct yagl_avl_traverser *trav)
-{
-    assert(trav != NULL);
-
-    return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
-}
-
-/*
- * Replaces the current item in |trav| by |new| and returns the item replaced.
- * |trav| must not have the null item selected.
- * The new item must not upset the ordering of the tree.
- */
-void *yagl_avl_t_replace(struct yagl_avl_traverser *trav, void *new)
-{
-    void *old;
-
-    assert(trav != NULL && trav->avl_node != NULL && new != NULL);
-    old = trav->avl_node->avl_data;
-    trav->avl_node->avl_data = new;
-    return old;
-}
-
-/*
- * Destroys |new| with |avl_destroy (new, destroy)|,
- * first setting right links of nodes in |stack| within |new|
- * to null pointers to avoid touching uninitialized data.
- */
-static void yagl_copy_error_recovery(struct yagl_avl_node **stack, int height,
-    struct yagl_avl_table *new, yagl_avl_item_func *destroy)
-{
-    assert(stack != NULL && height >= 0 && new != NULL);
-
-    for (; height > 2; height -= 2) {
-        stack[height - 1]->avl_link[1] = NULL;
-    }
-    yagl_avl_destroy(new, destroy);
-}
-
-/*
- * Copies |org| to a newly created tree, which is returned.
- * If |copy != NULL|, each data item in |org| is first passed to |copy|,
- * and the return values are inserted into the tree,
- * with |NULL| return values taken as indications of failure.
- * On failure, destroys the partially created new tree,
- * applying |destroy|, if non-null, to each item in the new tree so far,
- * and returns |NULL|.
- * If |allocator != NULL|, it is used for allocation in the new tree.
- * Otherwise, the same allocator used for |org| is used.
- */
-struct yagl_avl_table *yagl_avl_copy(const struct yagl_avl_table *org,
-    yagl_avl_copy_func *copy,
-    yagl_avl_item_func *destroy,
-    struct yagl_libavl_allocator *allocator)
-{
-    struct yagl_avl_node *stack[2 * (YAGL_AVL_MAX_HEIGHT + 1)];
-    int height = 0;
-
-    struct yagl_avl_table *new;
-    const struct yagl_avl_node *x;
-    struct yagl_avl_node *y;
-
-    assert(org != NULL);
-    new = yagl_avl_create(org->avl_compare, org->avl_param,
-        allocator != NULL ? allocator : org->avl_alloc);
-    if (new == NULL) {
-        return NULL;
-    }
-    new->avl_count = org->avl_count;
-    if (new->avl_count == 0) {
-        return new;
-    }
-
-    x = (const struct yagl_avl_node *) &org->avl_root;
-    y = (struct yagl_avl_node *) &new->avl_root;
-    for (;;) {
-        while (x->avl_link[0] != NULL) {
-            assert(height < 2 * (YAGL_AVL_MAX_HEIGHT + 1));
-
-            y->avl_link[0] = new->avl_alloc->libavl_malloc(new->avl_alloc,
-                sizeof(*y->avl_link[0]));
-            if (y->avl_link[0] == NULL) {
-                if (y != (struct yagl_avl_node *) &new->avl_root) {
-                    y->avl_data = NULL;
-                    y->avl_link[1] = NULL;
-                }
-
-                yagl_copy_error_recovery(stack, height, new, destroy);
-                return NULL;
-            }
-
-            stack[height++] = (struct yagl_avl_node *) x;
-            stack[height++] = y;
-            x = x->avl_link[0];
-            y = y->avl_link[0];
-        }
-        y->avl_link[0] = NULL;
-
-        for (;;) {
-            y->avl_balance = x->avl_balance;
-            if (copy == NULL) {
-                y->avl_data = x->avl_data;
-            } else {
-                y->avl_data = copy(x->avl_data, org->avl_param);
-                if (y->avl_data == NULL) {
-                    y->avl_link[1] = NULL;
-                    yagl_copy_error_recovery(stack, height, new, destroy);
-                    return NULL;
-                }
-            }
-
-            if (x->avl_link[1] != NULL) {
-                y->avl_link[1] = new->avl_alloc->libavl_malloc(new->avl_alloc,
-                    sizeof(*y->avl_link[1]));
-                if (y->avl_link[1] == NULL) {
-                    yagl_copy_error_recovery(stack, height, new, destroy);
-                    return NULL;
-                }
-
-                x = x->avl_link[1];
-                y = y->avl_link[1];
-                break;
-            } else {
-                y->avl_link[1] = NULL;
-            }
-
-            if (height <= 2) {
-                return new;
-            }
-
-            y = stack[--height];
-            x = stack[--height];
-        }
-    }
-}
-
-/*
- * Frees storage allocated for |tree|.
- * If |destroy != NULL|, applies it to each data item in inorder.
- */
-void yagl_avl_destroy(struct yagl_avl_table *tree, yagl_avl_item_func *destroy)
-{
-    struct yagl_avl_node *p, *q;
-
-    assert(tree != NULL);
-
-    for (p = tree->avl_root; p != NULL; p = q) {
-        if (p->avl_link[0] == NULL) {
-            q = p->avl_link[1];
-            if (destroy != NULL && p->avl_data != NULL) {
-                destroy(p->avl_data, tree->avl_param);
-            }
-            tree->avl_alloc->libavl_free(tree->avl_alloc, p);
-        } else {
-            q = p->avl_link[0];
-            p->avl_link[0] = q->avl_link[1];
-            q->avl_link[1] = p;
-        }
-    }
-
-    tree->avl_alloc->libavl_free(tree->avl_alloc, tree);
-}
-
-/*
- * Allocates |size| bytes of space using |malloc()|.
- * Returns a null pointer if allocation fails.
- */
-void *yagl_avl_malloc(struct yagl_libavl_allocator *allocator, size_t size)
-{
-    assert(allocator != NULL && size > 0);
-    return g_malloc(size);
-}
-
-/* Frees |block|. */
-void yagl_avl_free(struct yagl_libavl_allocator *allocator, void *block)
-{
-    assert(allocator != NULL && block != NULL);
-    g_free(block);
-}
-
-/* Default memory allocator that uses |g_malloc()| and |g_free()|. */
-struct yagl_libavl_allocator yagl_avl_allocator_default = {
-    yagl_avl_malloc, yagl_avl_free
-};
-
-#undef NDEBUG
-#include <assert.h>
-
-/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
-void (yagl_avl_assert_insert)(struct yagl_avl_table *table, void *item)
-{
-    void **p = yagl_avl_probe(table, item);
-    assert(p != NULL && *p == item);
-}
-
-/*
- * Asserts that |avl_delete()| really removes |item| from |table|,
- * and returns the removed item.
- */
-void *(yagl_avl_assert_delete)(struct yagl_avl_table *table, void *item)
-{
-    void *p = yagl_avl_delete(table, item);
-    assert(p != NULL);
-    return p;
-}
diff --git a/hw/yagl/yagl_avl.h b/hw/yagl/yagl_avl.h
deleted file mode 100644 (file)
index bb605fd..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * yagl
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * Stanislav Vorobiov <s.vorobiov@samsung.com>
- * Jinhyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-/*
- * AVL tree implementation from libavl project.
- */
-
-#ifndef _QEMU_YAGL_AVL_H
-#define _QEMU_YAGL_AVL_H
-
-#include "yagl_types.h"
-
-/* Function types. */
-typedef int yagl_avl_comparison_func(const void */*avl_a*/, const void */*avl_b*/,
-    void */*avl_param*/);
-typedef void yagl_avl_item_func(void */*avl_item*/, void */*avl_param*/);
-typedef void *yagl_avl_copy_func(void */*avl_item*/, void */*avl_param*/);
-
-/* Memory allocator. */
-struct yagl_libavl_allocator
-{
-    void *(*libavl_malloc)(struct yagl_libavl_allocator */*allocator*/,
-                           size_t /*libavl_size*/);
-    void (*libavl_free)(struct yagl_libavl_allocator */*allocator*/,
-                        void */*libavl_block*/);
-};
-
-/* Default memory allocator. */
-extern struct yagl_libavl_allocator yagl_avl_allocator_default;
-void *yagl_avl_malloc(struct yagl_libavl_allocator *allocator, size_t libavl_size);
-void yagl_avl_free(struct yagl_libavl_allocator *allocator, void *libavl_block);
-
-/* Maximum AVL tree height. */
-#define YAGL_AVL_MAX_HEIGHT 92
-
-/* Tree data structure. */
-struct yagl_avl_table
-{
-    struct yagl_avl_node *avl_root; /* Tree's root. */
-    yagl_avl_comparison_func *avl_compare; /* Comparison function. */
-    void *avl_param; /* Extra argument to |avl_compare|. */
-    struct yagl_libavl_allocator *avl_alloc; /* Memory allocator. */
-    size_t avl_count; /* Number of items in tree. */
-    unsigned long avl_generation; /* Generation number. */
-};
-
-/* An AVL tree node. */
-struct yagl_avl_node
-{
-    struct yagl_avl_node *avl_link[2]; /* Subtrees. */
-    void *avl_data; /* Pointer to data. */
-    signed char avl_balance; /* Balance factor. */
-};
-
-/* AVL traverser structure. */
-struct yagl_avl_traverser
-{
-    struct yagl_avl_table *avl_table; /* Tree being traversed. */
-    struct yagl_avl_node *avl_node; /* Current node in tree. */
-    struct yagl_avl_node *avl_stack[YAGL_AVL_MAX_HEIGHT];
-    /* All the nodes above |avl_node|. */
-    size_t avl_height; /* Number of nodes in |avl_parent|. */
-    unsigned long avl_generation; /* Generation number. */
-};
-
-/* Table functions. */
-struct yagl_avl_table *yagl_avl_create(yagl_avl_comparison_func *compare,
-    void *param,
-    struct yagl_libavl_allocator *allocator);
-struct yagl_avl_table *yagl_avl_copy(const struct yagl_avl_table *org,
-    yagl_avl_copy_func *copy,
-    yagl_avl_item_func *destroy, struct yagl_libavl_allocator *allocator);
-void yagl_avl_destroy(struct yagl_avl_table *tree, yagl_avl_item_func *destroy);
-void **yagl_avl_probe(struct yagl_avl_table *tree, void *item);
-void *yagl_avl_insert(struct yagl_avl_table *table, void *item);
-void *yagl_avl_replace(struct yagl_avl_table *table, void *item);
-void *yagl_avl_delete(struct yagl_avl_table *tree, const void *item);
-void *yagl_avl_find(const struct yagl_avl_table *tree, const void *item);
-void yagl_avl_assert_insert(struct yagl_avl_table *table, void *item);
-void *yagl_avl_assert_delete(struct yagl_avl_table *table, void *item);
-
-#define yagl_avl_count(table) ((size_t)(table)->avl_count)
-
-/* Table traverser functions. */
-void yagl_avl_t_init(struct yagl_avl_traverser *trav,
-                     struct yagl_avl_table *tree);
-void *yagl_avl_t_first(struct yagl_avl_traverser *trav,
-                       struct yagl_avl_table *tree);
-void *yagl_avl_t_last(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree);
-void *yagl_avl_t_find(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree,
-                      void *item);
-void *yagl_avl_t_insert(struct yagl_avl_traverser *trav,
-                        struct yagl_avl_table *tree,
-                        void *item);
-void *yagl_avl_t_copy(struct yagl_avl_traverser *trav,
-                      const struct yagl_avl_traverser *src);
-void *yagl_avl_t_next(struct yagl_avl_traverser *trav);
-void *yagl_avl_t_prev(struct yagl_avl_traverser *trav);
-void *yagl_avl_t_cur(struct yagl_avl_traverser *trav);
-void *yagl_avl_t_replace(struct yagl_avl_traverser *trav, void *new_item);
-
-#endif
index 40fd897da7950915b1f6c9d240ed01eae65c9da6..d8262dca0aa501c62081dd92113c7054843d505f 100644 (file)
  */
 
 #include "yagl_object_map.h"
-#include "yagl_avl.h"
 
-struct yagl_object_map_entry
+static void yagl_object_map_entry_destroy_func(gpointer data)
 {
-    yagl_object_name local_name;
+    struct yagl_object *item = data;
 
-    struct yagl_object *obj;
-};
-
-static int yagl_object_map_entry_comparison_func(const void *avl_a,
-                                                 const void *avl_b,
-                                                 void *avl_param)
-{
-    const struct yagl_object_map_entry *a = avl_a;
-    const struct yagl_object_map_entry *b = avl_b;
-
-    if (a->local_name < b->local_name) {
-        return -1;
-    } else if (a->local_name > b->local_name) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static void yagl_object_map_entry_destroy_func(void *avl_item, void *avl_param)
-{
-    struct yagl_object_map_entry *item = avl_item;
-
-    item->obj->destroy(item->obj);
-
-    g_free(item);
+    item->destroy(item);
 }
 
 struct yagl_object_map *yagl_object_map_create(void)
 {
     struct yagl_object_map *object_map = g_malloc0(sizeof(struct yagl_object_map));
 
-    object_map->entries = yagl_avl_create(&yagl_object_map_entry_comparison_func,
-                                          object_map,
-                                          NULL);
+    object_map->entries = g_hash_table_new_full(g_direct_hash,
+                                                g_direct_equal,
+                                                NULL,
+                                                &yagl_object_map_entry_destroy_func);
+
     assert(object_map->entries);
 
     return object_map;
@@ -76,7 +52,8 @@ struct yagl_object_map *yagl_object_map_create(void)
 
 void yagl_object_map_destroy(struct yagl_object_map *object_map)
 {
-    yagl_avl_destroy(object_map->entries, &yagl_object_map_entry_destroy_func);
+    g_hash_table_destroy(object_map->entries);
+
     object_map->entries = NULL;
 
     g_free(object_map);
@@ -86,50 +63,38 @@ void yagl_object_map_add(struct yagl_object_map *object_map,
                          yagl_object_name local_name,
                          struct yagl_object *obj)
 {
-    struct yagl_object_map_entry *item =
-        g_malloc0(sizeof(struct yagl_object_map_entry));
+    guint size = g_hash_table_size(object_map->entries);
 
-    item->local_name = local_name;
-    item->obj = obj;
+    g_hash_table_insert(object_map->entries,
+                        GUINT_TO_POINTER(local_name),
+                        obj);
 
-    yagl_avl_assert_insert(object_map->entries, item);
+    assert(g_hash_table_size(object_map->entries) > size);
 }
 
 void yagl_object_map_remove(struct yagl_object_map *object_map,
                             yagl_object_name local_name)
 {
-    void *item;
-    struct yagl_object_map_entry dummy;
-
-    dummy.local_name = local_name;
+    guint size = g_hash_table_size(object_map->entries);
 
-    item = yagl_avl_assert_delete(object_map->entries, &dummy);
+    g_hash_table_remove(object_map->entries, GUINT_TO_POINTER(local_name));
 
-    yagl_object_map_entry_destroy_func(item, object_map->entries->avl_param);
+    assert(g_hash_table_size(object_map->entries) < size);
 }
 
 void yagl_object_map_remove_all(struct yagl_object_map *object_map)
 {
-    yagl_avl_destroy(object_map->entries, &yagl_object_map_entry_destroy_func);
-
-    object_map->entries = yagl_avl_create(&yagl_object_map_entry_comparison_func,
-                                          object_map,
-                                          NULL);
-    assert(object_map->entries);
+    g_hash_table_remove_all(object_map->entries);
 }
 
 yagl_object_name yagl_object_map_get(struct yagl_object_map *object_map,
                                      yagl_object_name local_name)
 {
-    struct yagl_object_map_entry *item;
-    struct yagl_object_map_entry dummy;
-
-    dummy.local_name = local_name;
-
-    item = yagl_avl_find(object_map->entries, &dummy);
+    struct yagl_object *item = g_hash_table_lookup(object_map->entries,
+                                                   GUINT_TO_POINTER(local_name));
 
     if (item) {
-        return item->obj->global_name;
+        return item->global_name;
     } else {
         assert(0);
         return 0;
index cd8ee4aa99d8bcf630e5550a51317cf0388d84bd..c4d8c3c79ded45c586ea4825ffb988790c5d495d 100644 (file)
@@ -31,8 +31,7 @@
 #define _QEMU_YAGL_OBJECT_MAP_H
 
 #include "yagl_types.h"
-
-struct yagl_avl_table;
+#include <glib.h>
 
 struct yagl_object
 {
@@ -43,7 +42,7 @@ struct yagl_object
 
 struct yagl_object_map
 {
-    struct yagl_avl_table *entries;
+    GHashTable *entries;
 };
 
 struct yagl_object_map *yagl_object_map_create(void);