[gjs/wip/ptomato/mozjs52: 34/37] WIP - js: Remove JSRuntime



commit 14966f67a47193006a1c294b7adbabc42fddb7ee
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue May 2 23:15:10 2017 -0700

    WIP - js: Remove JSRuntime
    
    JSRuntime is merged into JSContext in SpiderMonkey 52.
    
    FIXME: Should probably reorganize these files since "runtime.cpp" doesn't
    make sense anymore.

 gi/function.cpp       |    4 +-
 gi/value.cpp          |    5 +-
 gjs/context-private.h |    3 +
 gjs/context.cpp       |   68 +++++++++++++++++--
 gjs/runtime.cpp       |  182 ++++++++-----------------------------------------
 gjs/runtime.h         |    8 +--
 6 files changed, 100 insertions(+), 170 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index 1a89821..32d518a 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -173,7 +173,6 @@ gjs_callback_closure(ffi_cif *cif,
                      void *data)
 {
     JSContext *context;
-    JSRuntime *runtime;
     JSObject *func_obj;
     GjsCallbackTrampoline *trampoline;
     int i, n_args, n_jsargs, n_outargs;
@@ -186,8 +185,7 @@ gjs_callback_closure(ffi_cif *cif,
     gjs_callback_trampoline_ref(trampoline);
 
     context = trampoline->context;
-    runtime = JS_GetRuntime(context);
-    if (G_UNLIKELY (gjs_runtime_is_sweeping(runtime))) {
+    if (G_UNLIKELY(_gjs_context_is_sweeping(context))) {
         g_critical("Attempting to call back into JSAPI during the sweeping phase of GC. "
                    "This is most likely caused by not destroying a Clutter actor or Gtk+ "
                    "widget with ::destroy signals connected, but can also be caused by "
diff --git a/gi/value.cpp b/gi/value.cpp
index 9c95ead..2e6032d 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -36,6 +36,7 @@
 #include "union.h"
 #include "gtype.h"
 #include "gerror.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-wrapper.h"
 
 #include <girepository.h>
@@ -118,7 +119,6 @@ closure_marshal(GClosure        *closure,
                 gpointer         marshal_data)
 {
     JSContext *context;
-    JSRuntime *runtime;
     JSObject *obj;
     unsigned i;
     GSignalQuery signal_query = { 0, };
@@ -137,8 +137,7 @@ closure_marshal(GClosure        *closure,
     }
 
     context = gjs_closure_get_context(closure);
-    runtime = JS_GetRuntime(context);
-    if (G_UNLIKELY (gjs_runtime_is_sweeping(runtime))) {
+    if (G_UNLIKELY(_gjs_context_is_sweeping(context))) {
         GSignalInvocationHint *hint = (GSignalInvocationHint*) invocation_hint;
 
         g_critical("Attempting to call back into JSAPI during the sweeping phase of GC. "
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 2d8834d..4006eee 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -27,6 +27,7 @@
 #include <inttypes.h>
 
 #include "context.h"
+#include "jsapi-wrapper.h"
 
 G_BEGIN_DECLS
 
@@ -42,6 +43,8 @@ bool _gjs_context_get_is_owner_thread(GjsContext *js_context);
 bool _gjs_context_should_exit(GjsContext *js_context,
                               uint8_t    *exit_code_p);
 
+bool _gjs_context_is_sweeping(JSContext *cx);
+
 G_END_DECLS
 
 #endif  /* __GJS_CONTEXT_PRIVATE_H__ */
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 9d91431..891083a 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -66,7 +66,6 @@ static void     gjs_context_set_property      (GObject               *object,
 struct _GjsContext {
     GObject parent;
 
-    JSRuntime *runtime;
     JSContext *context;
     JS::Heap<JSObject*> global;
     GThread *owner_thread;
@@ -76,6 +75,7 @@ struct _GjsContext {
     char **search_path;
 
     bool destroying;
+    bool in_gc_sweep;
 
     bool should_exit;
     uint8_t exit_code;
@@ -265,6 +265,59 @@ gjs_printerr(JSContext *context,
 }
 
 static void
+on_finalize(JSFreeOp         *fop,
+            JSFinalizeStatus  status,
+            bool              isCompartment,
+            void             *data)
+{
+    auto js_context = static_cast<GjsContext *>(data);
+    /* Implementation note for mozjs 24:
+     * sweeping happens in two phases, in the first phase all
+     * GC things from the allocation arenas are queued for
+     * sweeping, then the actual sweeping happens.
+     * The first phase is marked by JSFINALIZE_GROUP_START,
+     * the second one by JSFINALIZE_GROUP_END, and finally
+     * we will see JSFINALIZE_COLLECTION_END at the end of
+     * all GC.
+     * (see jsgc.cpp, BeginSweepPhase/BeginSweepingZoneGroup
+     * and SweepPhase, all called from IncrementalCollectSlice).
+     * Incremental GC muds the waters, because BeginSweepPhase
+     * is always run to entirety, but SweepPhase can be run
+     * incrementally and mixed with JS code runs or even
+     * native code, when MaybeGC/IncrementalGC return.
+     *
+     * Luckily for us, objects are treated specially, and
+     * are not really queued for deferred incremental
+     * finalization (unless they are marked for background
+     * sweeping). Instead, they are finalized immediately
+     * during phase 1, so the following guarantees are
+     * true (and we rely on them)
+     * - phase 1 of GC will begin and end in the same JSAPI
+     *   call (ie, our callback will be called with GROUP_START
+     *   and the triggering JSAPI call will not return until
+     *   we see a GROUP_END)
+     * - object finalization will begin and end in the same
+     *   JSAPI call
+     * - therefore, if there is a finalizer frame somewhere
+     *   in the stack, gjs_runtime_is_sweeping() will return
+     *   true.
+     *
+     * Comments in mozjs24 imply that this behavior might
+     * change in the future, but it hasn't changed in
+     * mozilla-central as of 2014-02-23. In addition to
+     * that, the mozilla-central version has a huge comment
+     * in a different portion of the file, explaining
+     * why finalization of objects can't be mixed with JS
+     * code, so we can probably rely on this behavior.
+     */
+
+    if (status == JSFINALIZE_GROUP_START)
+        js_context->in_gc_sweep = true;
+    else if (status == JSFINALIZE_GROUP_END)
+        js_context->in_gc_sweep = false;
+}
+
+static void
 on_garbage_collect(JSContext *cx,
                    JSGCStatus status,
                    void      *data)
@@ -433,7 +486,6 @@ gjs_context_dispose(GObject *object)
         /* Tear down JS */
         JS_DestroyContext(js_context->context);
         js_context->context = NULL;
-        g_clear_pointer(&js_context->runtime, gjs_runtime_unref);
     }
 }
 
@@ -481,11 +533,9 @@ gjs_context_constructed(GObject *object)
 
     G_OBJECT_CLASS(gjs_context_parent_class)->constructed(object);
 
-    js_context->runtime = gjs_runtime_ref();
-
     js_context->owner_thread = g_thread_self();
 
-    js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */);
+    js_context->context = gjs_create_js_context(js_context);
     if (js_context->context == NULL)
         g_error("Failed to create javascript context");
 
@@ -500,6 +550,7 @@ gjs_context_constructed(GObject *object)
 
     JS_BeginRequest(js_context->context);
 
+    JS_AddFinalizeCallback(js_context->context, on_finalize, js_context);
     JS_SetGCCallback(js_context->context, on_garbage_collect, js_context);
 
     /* set ourselves as the private data */
@@ -669,6 +720,13 @@ _gjs_context_get_is_owner_thread(GjsContext *js_context)
     return js_context->owner_thread == g_thread_self();
 }
 
+bool
+_gjs_context_is_sweeping(JSContext *cx)
+{
+    auto js_context = static_cast<GjsContext *>(JS_GetContextPrivate(cx));
+    return js_context->in_gc_sweep;
+}
+
 /**
  * gjs_context_maybe_gc:
  * @context: a #GjsContext
diff --git a/gjs/runtime.cpp b/gjs/runtime.cpp
index 3c9c206..356d687 100644
--- a/gjs/runtime.cpp
+++ b/gjs/runtime.cpp
@@ -26,6 +26,7 @@
 #include "jsapi-wrapper.h"
 #include <js/Initialization.h>
 
+#include "context.h"
 #include "jsapi-util.h"
 #include "runtime.h"
 
@@ -34,19 +35,6 @@
 #include <windows.h>
 #endif
 
-struct RuntimeData {
-  unsigned refcount;
-  bool in_gc_sweep;
-};
-
-bool
-gjs_runtime_is_sweeping (JSRuntime *runtime)
-{
-  RuntimeData *data = (RuntimeData*) JS_GetRuntimePrivate(runtime);
-
-  return data->in_gc_sweep;
-}
-
 /* Implementations of locale-specific operations; these are used
  * in the implementation of String.localeCompare(), Date.toLocaleDateString(),
  * and so forth. We take the straight-forward approach of converting
@@ -144,18 +132,6 @@ gjs_locale_to_unicode (JSContext  *context,
     return success;
 }
 
-static void
-destroy_runtime(gpointer data)
-{
-    JSRuntime *runtime = (JSRuntime *) data;
-    RuntimeData *rtdata = (RuntimeData *) JS_GetRuntimePrivate(runtime);
-
-    JS_DestroyRuntime(runtime);
-    g_free(rtdata);
-}
-
-static GPrivate thread_runtime = G_PRIVATE_INIT(destroy_runtime);
-
 static JSLocaleCallbacks gjs_locale_callbacks =
 {
     gjs_locale_to_upper_case,
@@ -164,68 +140,6 @@ static JSLocaleCallbacks gjs_locale_callbacks =
     gjs_locale_to_unicode
 };
 
-static void
-gjs_finalize_callback(JSFreeOp         *fop,
-                      JSFinalizeStatus  status,
-                      bool              isCompartment,
-                      void             *user_data)
-{
-  RuntimeData *data = static_cast<RuntimeData *>(user_data);
-
-  /* Implementation note for mozjs 24:
-     sweeping happens in two phases, in the first phase all
-     GC things from the allocation arenas are queued for
-     sweeping, then the actual sweeping happens.
-     The first phase is marked by JSFINALIZE_GROUP_START,
-     the second one by JSFINALIZE_GROUP_END, and finally
-     we will see JSFINALIZE_COLLECTION_END at the end of
-     all GC.
-     (see jsgc.cpp, BeginSweepPhase/BeginSweepingZoneGroup
-     and SweepPhase, all called from IncrementalCollectSlice).
-     Incremental GC muds the waters, because BeginSweepPhase
-     is always run to entirety, but SweepPhase can be run
-     incrementally and mixed with JS code runs or even
-     native code, when MaybeGC/IncrementalGC return.
-
-     Luckily for us, objects are treated specially, and
-     are not really queued for deferred incremental
-     finalization (unless they are marked for background
-     sweeping). Instead, they are finalized immediately
-     during phase 1, so the following guarantees are
-     true (and we rely on them)
-     - phase 1 of GC will begin and end in the same JSAPI
-       call (ie, our callback will be called with GROUP_START
-       and the triggering JSAPI call will not return until
-       we see a GROUP_END)
-     - object finalization will begin and end in the same
-       JSAPI call
-     - therefore, if there is a finalizer frame somewhere
-       in the stack, gjs_runtime_is_sweeping() will return
-       true.
-
-     Comments in mozjs24 imply that this behavior might
-     change in the future, but it hasn't changed in
-     mozilla-central as of 2014-02-23. In addition to
-     that, the mozilla-central version has a huge comment
-     in a different portion of the file, explaining
-     why finalization of objects can't be mixed with JS
-     code, so we can probably rely on this behavior.
-  */
-
-  if (status == JSFINALIZE_GROUP_START)
-    data->in_gc_sweep = true;
-  else if (status == JSFINALIZE_GROUP_END)
-    data->in_gc_sweep = false;
-}
-
-/* Destroys the current thread's runtime regardless of refcount. No-op if there
- * is no runtime */
-static void
-gjs_destroy_runtime_for_current_thread(void)
-{
-    g_private_replace(&thread_runtime, NULL);
-}
-
 #ifdef G_OS_WIN32
 HMODULE gjs_dll;
 static bool gjs_is_inited = false;
@@ -243,7 +157,6 @@ LPVOID    lpvReserved)
     break;
 
   case DLL_THREAD_DETACH:
-    gjs_destroy_runtime_for_current_thread();
     JS_ShutDown ();
     break;
 
@@ -264,8 +177,6 @@ public:
     }
 
     ~GjsInit() {
-        /* No-op if the runtime was already destroyed */
-        gjs_destroy_runtime_for_current_thread();
         JS_ShutDown();
     }
 
@@ -277,69 +188,32 @@ public:
 static GjsInit gjs_is_inited;
 #endif
 
-static JSRuntime *
-gjs_runtime_for_current_thread(void)
-{
-    JSRuntime *runtime = (JSRuntime *) g_private_get(&thread_runtime);
-    RuntimeData *data;
-
-    if (!runtime) {
-        g_assert(gjs_is_inited);
-        runtime = JS_NewRuntime(32 * 1024 * 1024 /* max bytes */);
-        if (runtime == NULL)
-            g_error("Failed to create javascript runtime");
-
-        data = g_new0(RuntimeData, 1);
-        JS_SetRuntimePrivate(runtime, data);
-
-        // commented are defaults in moz-24
-        JS_SetNativeStackQuota(runtime, 1024*1024);
-        JS_SetGCParameter(runtime, JSGC_MAX_MALLOC_BYTES, 128*1024*1024);
-        JS_SetGCParameter(runtime, JSGC_MAX_BYTES, -1);
-        JS_SetGCParameter(runtime, JSGC_MODE, JSGC_MODE_INCREMENTAL);
-        JS_SetGCParameter(runtime, JSGC_SLICE_TIME_BUDGET, 10); /* ms */
-        // JS_SetGCParameter(runtime, JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000); /* ms */
-        JS_SetGCParameter(runtime, JSGC_DYNAMIC_MARK_SLICE, true);
-        JS_SetGCParameter(runtime, JSGC_DYNAMIC_HEAP_GROWTH, true);
-        // JS_SetGCParameter(runtime, JSGC_LOW_FREQUENCY_HEAP_GROWTH, 150);
-        // JS_SetGCParameter(runtime, JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 150);
-        // JS_SetGCParameter(runtime, JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300);
-        // JS_SetGCParameter(runtime, JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100);
-        // JS_SetGCParameter(runtime, JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500);
-        // JS_SetGCParameter(runtime, JSGC_ALLOCATION_THRESHOLD, 30);
-        // JS_SetGCParameter(runtime, JSGC_DECOMMIT_THRESHOLD, 32);
-        JS_SetLocaleCallbacks(runtime, &gjs_locale_callbacks);
-        JS_AddFinalizeCallback(runtime, gjs_finalize_callback, data);
-        JS_SetErrorReporter(runtime, gjs_error_reporter);
-
-        g_private_set(&thread_runtime, runtime);
-    }
-
-    return runtime;
-}
-
-/* These two act on the current thread's runtime. In the future they will go
- * away because SpiderMonkey is going to merge JSContext and JSRuntime.
- */
-
-/* Creates a new runtime with one reference if there is no runtime yet */
-JSRuntime *
-gjs_runtime_ref(void)
-{
-    JSRuntime *rt = static_cast<JSRuntime *>(gjs_runtime_for_current_thread());
-    RuntimeData *data = static_cast<RuntimeData *>(JS_GetRuntimePrivate(rt));
-    g_atomic_int_inc(&data->refcount);
-    return rt;
-}
-
-/* No-op if there is no runtime */
-void
-gjs_runtime_unref(void)
+JSContext *
+gjs_create_js_context(GjsContext *js_context)
 {
-    JSRuntime *rt = static_cast<JSRuntime *>(g_private_get(&thread_runtime));
-    if (rt == NULL)
-        return;
-    RuntimeData *data = static_cast<RuntimeData *>(JS_GetRuntimePrivate(rt));
-    if (g_atomic_int_dec_and_test(&data->refcount))
-        gjs_destroy_runtime_for_current_thread();
+    g_assert(gjs_is_inited);
+    JSContext *cx = JS_NewContext(32 * 1024 * 1024 /* max bytes */);
+    if (!cx)
+        g_error("Failed to create javascript runtime");
+
+    // commented are defaults in moz-24
+    JS_SetNativeStackQuota(cx, 1024 * 1024);
+    JS_SetGCParameter(cx, JSGC_MAX_MALLOC_BYTES, 128 * 1024 * 1024);
+    JS_SetGCParameter(cx, JSGC_MAX_BYTES, -1);
+    JS_SetGCParameter(cx, JSGC_MODE, JSGC_MODE_INCREMENTAL);
+    JS_SetGCParameter(cx, JSGC_SLICE_TIME_BUDGET, 10); /* ms */
+    // JS_SetGCParameter(cx, JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000); /* ms */
+    JS_SetGCParameter(cx, JSGC_DYNAMIC_MARK_SLICE, true);
+    JS_SetGCParameter(cx, JSGC_DYNAMIC_HEAP_GROWTH, true);
+    // JS_SetGCParameter(cx, JSGC_LOW_FREQUENCY_HEAP_GROWTH, 150);
+    // JS_SetGCParameter(cx, JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 150);
+    // JS_SetGCParameter(cx, JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300);
+    // JS_SetGCParameter(cx, JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100);
+    // JS_SetGCParameter(cx, JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500);
+    // JS_SetGCParameter(cx, JSGC_ALLOCATION_THRESHOLD, 30);
+    // JS_SetGCParameter(cx, JSGC_DECOMMIT_THRESHOLD, 32);
+    JS_SetLocaleCallbacks(cx, &gjs_locale_callbacks);
+    JS_SetErrorReporter(cx, gjs_error_reporter);
+
+    return cx;
 }
diff --git a/gjs/runtime.h b/gjs/runtime.h
index 6f31fd2..19f55a6 100644
--- a/gjs/runtime.h
+++ b/gjs/runtime.h
@@ -24,11 +24,9 @@
 #ifndef __GJS_RUNTIME_H__
 #define __GJS_RUNTIME_H__
 
-#include <stdbool.h>
+#include "context.h"
+#include "jsapi-wrapper.h"
 
-JSRuntime *gjs_runtime_ref(void);
-void gjs_runtime_unref(void);
-
-bool        gjs_runtime_is_sweeping        (JSRuntime *runtime);
+JSContext *gjs_create_js_context(GjsContext *js_context);
 
 #endif /* __GJS_RUNTIME_H__ */


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