[gjs: 9/26] context: Use tracing for promise job queue



commit ad90c9312ce94f2327f5be016c46210713031b64
Author: Philip Chimento <philip chimento gmail com>
Date:   Wed Jan 23 16:25:19 2019 -0800

    context: Use tracing for promise job queue
    
    Previously we used PersistentRooted to prevent the promise job queue
    from being garbage collected. This is how it was done in SpiderMonkey's
    demo interactive interpreter. However, PersistentRooted can be wasteful
    of resources since it links everything into a big linked list. We
    already have a trace() callback for GjsContextPrivate, so we can just
    trace the promise job objects in there.

 gjs/context-private.h |  2 +-
 gjs/context.cpp       | 21 ++++++++-------------
 2 files changed, 9 insertions(+), 14 deletions(-)
---
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 48131b92..5474e1e9 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -75,7 +75,7 @@ class GjsContextPrivate {
 
     GjsAtoms m_atoms;
 
-    JS::PersistentRooted<JobQueue>* m_job_queue;
+    JobQueue m_job_queue;
     unsigned m_idle_drain_handler;
 
     std::unordered_map<uint64_t, GjsAutoChar> m_unhandled_rejection_stacks;
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 45447641..e55bc5f9 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -299,6 +299,7 @@ void GjsContextPrivate::trace(JSTracer* trc, void* data) {
     auto* gjs = static_cast<GjsContextPrivate*>(data);
     JS::TraceEdge<JSObject*>(trc, &gjs->m_global, "GJS global object");
     gjs->m_atoms.trace(trc);
+    gjs->m_job_queue.trace(trc);
 }
 
 void GjsContextPrivate::warn_about_unhandled_promise_rejections(void) {
@@ -387,7 +388,6 @@ void GjsContextPrivate::dispose(void) {
         m_global = nullptr;
 
         gjs_debug(GJS_DEBUG_CONTEXT, "Freeing allocated resources");
-        delete m_job_queue;
         delete m_fundamental_table;
         delete m_gtype_table;
 
@@ -465,10 +465,6 @@ GjsContextPrivate::GjsContextPrivate(JSContext* cx, GjsContext* public_context)
         }
     }
 
-    m_job_queue = new JS::PersistentRooted<JobQueue>(m_cx);
-    if (!m_job_queue)
-        g_error("Failed to initialize promise job queue");
-
     JSRuntime* rt = JS_GetRuntime(m_cx);
     m_fundamental_table = new JS::WeakCache<FundamentalTable>(rt);
     if (!m_fundamental_table->init())
@@ -643,11 +639,11 @@ gboolean GjsContextPrivate::drain_job_queue_idle_handler(void* data) {
 /* See engine.cpp and JS::SetEnqueuePromiseJobCallback(). */
 bool GjsContextPrivate::enqueue_job(JS::HandleObject job) {
     if (m_idle_drain_handler)
-        g_assert(m_job_queue->length() > 0);
+        g_assert(m_job_queue.length() > 0);
     else
-        g_assert(m_job_queue->length() == 0);
+        g_assert(m_job_queue.length() == 0);
 
-    if (!m_job_queue->append(job)) {
+    if (!m_job_queue.append(job)) {
         JS_ReportOutOfMemory(m_cx);
         return false;
     }
@@ -672,7 +668,6 @@ bool GjsContextPrivate::enqueue_job(JS::HandleObject job) {
  */
 bool GjsContextPrivate::run_jobs(void) {
     bool retval = true;
-    g_assert(m_job_queue);
 
     if (m_draining_job_queue || m_should_exit)
         return true;
@@ -688,12 +683,12 @@ bool GjsContextPrivate::run_jobs(void) {
     /* Execute jobs in a loop until we've reached the end of the queue.
      * Since executing a job can trigger enqueueing of additional jobs,
      * it's crucial to recheck the queue length during each iteration. */
-    for (size_t ix = 0; ix < m_job_queue->length(); ix++) {
+    for (size_t ix = 0; ix < m_job_queue.length(); ix++) {
         /* A previous job might have set this flag. e.g., System.exit(). */
         if (m_should_exit)
             break;
 
-        job = m_job_queue->get()[ix];
+        job = m_job_queue[ix];
 
         /* It's possible that job draining was interrupted prematurely,
          * leaving the queue partly processed. In that case, slots for
@@ -702,7 +697,7 @@ bool GjsContextPrivate::run_jobs(void) {
         if (!job)
             continue;
 
-        m_job_queue->get()[ix] = nullptr;
+        m_job_queue[ix] = nullptr;
         {
             JSAutoCompartment ac(m_cx, job);
             if (!JS::Call(m_cx, JS::UndefinedHandleValue, job, args, &rval)) {
@@ -725,7 +720,7 @@ bool GjsContextPrivate::run_jobs(void) {
     }
 
     m_draining_job_queue = false;
-    m_job_queue->clear();
+    m_job_queue.clear();
     if (m_idle_drain_handler) {
         g_source_remove(m_idle_drain_handler);
         m_idle_drain_handler = 0;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]