[gjs/wip/ptomato/mozjs38: 5/28] keep-alive: Update hash keys when objects move
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/ptomato/mozjs38: 5/28] keep-alive: Update hash keys when objects move
- Date: Wed, 25 Jan 2017 02:35:26 +0000 (UTC)
commit 71a48cad17432859304d9890ccb4c46436514add
Author: Philip Chimento <philip endlessm com>
Date: Wed Jan 18 17:18:43 2017 -0800
keep-alive: Update hash keys when objects move
The garbage collector can change the locations of objects. Since we use
the object pointer as part of the hash function for the keep-alive hash
table, an object moving would invalidate the hash table key. Therefore,
we remove and reinsert each key if tracing changed the pointer's
location.
https://bugzilla.gnome.org/show_bug.cgi?id=776966
gi/keep-alive.cpp | 35 +++++++++++++++++++++++++----------
1 files changed, 25 insertions(+), 10 deletions(-)
---
diff --git a/gi/keep-alive.cpp b/gi/keep-alive.cpp
index 8adbabc..488a771 100644
--- a/gi/keep-alive.cpp
+++ b/gi/keep-alive.cpp
@@ -113,16 +113,10 @@ keep_alive_finalize(JSFreeOp *fop,
}
static void
-trace_foreach(void *key,
- void *value,
- void *data)
+reinsert(Child *child,
+ GHashTable *children)
{
- Child *child = (Child *) value;
- JSTracer *tracer = (JSTracer *) data;
-
- if (child->child != NULL) {
- JS_CallHeapObjectTracer(tracer, &child->child, "keep-alive::val");
- }
+ g_hash_table_replace(children, child, child);
}
static void
@@ -138,7 +132,28 @@ keep_alive_trace(JSTracer *tracer,
g_assert(!priv->inside_trace);
priv->inside_trace = true;
- g_hash_table_foreach(priv->children, trace_foreach, tracer);
+
+ GHashTableIter iter;
+ void *key;
+ GSList *children_to_reinsert = NULL;
+ g_hash_table_iter_init(&iter, priv->children);
+ while (g_hash_table_iter_next(&iter, &key, NULL)) {
+ Child *child = static_cast<Child *>(key);
+ JSObject *old_key = child->child.get();
+ JS_CallHeapObjectTracer(tracer, &child->child, "keep-alive::val");
+
+ /* Remove and reinsert if the pointer's location was updated,
+ * because that means the hash value is different */
+ if (child->child.get() != old_key) {
+ g_hash_table_iter_steal(&iter);
+ children_to_reinsert = g_slist_prepend(children_to_reinsert,
+ child);
+ }
+ }
+ g_slist_foreach(children_to_reinsert, (GFunc) reinsert,
+ priv->children);
+ g_slist_free(children_to_reinsert);
+
priv->inside_trace = false;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]