[gjs/wip/ptomato/mozjs52: 1/5] js: Remove JSRuntime



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

    js: Remove JSRuntime
    
    JSRuntime is merged into JSContext in SpiderMonkey 52.
    
    We reorganize things a bit to reflect the new situation. The files
    runtime.cpp and runtime.h are renamed to engine.cpp and engine.h, and
    will contain everything having to do with the SpiderMonkey engine:
    initializing the JSContext, and any callbacks that the engine requires
    embedders to set.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=784196

 gi/function.cpp                 |    4 +-
 gi/value.cpp                    |    5 +-
 gjs-srcs.mk                     |    4 +-
 gjs/context-private.h           |    6 ++
 gjs/context.cpp                 |   90 ++++++++--------------
 gjs/{runtime.cpp => engine.cpp} |  159 +++++++++++++++------------------------
 gjs/{runtime.h => engine.h}     |   14 ++--
 gjs/jsapi-util.h                |    1 -
 8 files changed, 110 insertions(+), 173 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-srcs.mk b/gjs-srcs.mk
index b7c1efd..5d41951 100644
--- a/gjs-srcs.mk
+++ b/gjs-srcs.mk
@@ -54,6 +54,8 @@ gjs_srcs =                            \
        gjs/context-private.h           \
        gjs/coverage-internal.h         \
        gjs/coverage.cpp                \
+       gjs/engine.cpp                  \
+       gjs/engine.h                    \
        gjs/global.cpp                  \
        gjs/global.h                    \
        gjs/importer.cpp                \
@@ -77,8 +79,6 @@ gjs_srcs =                            \
        gjs/module.cpp                  \
        gjs/native.cpp                  \
        gjs/native.h                    \
-       gjs/runtime.cpp                 \
-       gjs/runtime.h                   \
        gjs/stack.cpp                   \
        modules/modules.cpp             \
        modules/modules.h               \
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 2d8834d..d6207da 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,11 @@ bool _gjs_context_get_is_owner_thread(GjsContext *js_context);
 bool _gjs_context_should_exit(GjsContext *js_context,
                               uint8_t    *exit_code_p);
 
+void _gjs_context_set_sweeping(GjsContext *js_context,
+                               bool        sweeping);
+
+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 569b902..b453fcc 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -28,6 +28,7 @@
 #include <gio/gio.h>
 
 #include "context-private.h"
+#include "engine.h"
 #include "global.h"
 #include "importer.h"
 #include "jsapi-private.h"
@@ -35,7 +36,6 @@
 #include "jsapi-wrapper.h"
 #include "native.h"
 #include "byteArray.h"
-#include "runtime.h"
 #include "gi/object.h"
 #include "gi/repo.h"
 
@@ -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;
@@ -114,19 +114,6 @@ static GMutex contexts_lock;
 static GList *all_contexts = NULL;
 
 static void
-on_garbage_collect(JSContext *cx,
-                   JSGCStatus status,
-                   void      *data)
-{
-    /* We finalize any pending toggle refs before doing any garbage collection,
-     * so that we can collect the JS wrapper objects, and in order to minimize
-     * the chances of objects having a pending toggle up queued when they are
-     * garbage collected. */
-    if (status == JSGC_BEGIN)
-        gjs_object_clear_toggles();
-}
-
-static void
 gjs_context_init(GjsContext *js_context)
 {
     gjs_context_make_current(js_context);
@@ -243,7 +230,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);
     }
 }
 
@@ -283,74 +269,48 @@ 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 */);
-    if (js_context->context == NULL)
+    JSContext *cx = gjs_create_js_context(js_context);
+    if (!cx)
         g_error("Failed to create javascript context");
+    js_context->context = cx;
 
     for (i = 0; i < GJS_STRING_LAST; i++) {
-        js_context->const_strings[i] =
-            new JS::PersistentRootedId(js_context->context,
-                gjs_intern_string_to_id(js_context->context, const_strings[i]));
-    }
-
-    JS_BeginRequest(js_context->context);
-
-    JS_SetGCCallback(js_context->context, on_garbage_collect, js_context);
-
-    /* set ourselves as the private data */
-    JS_SetContextPrivate(js_context->context, js_context);
-
-    /* setExtraWarnings: Be extra strict about code that might hide a bug */
-    if (!g_getenv("GJS_DISABLE_EXTRA_WARNINGS")) {
-        gjs_debug(GJS_DEBUG_CONTEXT, "Enabling extra warnings");
-        JS::ContextOptionsRef(js_context->context).setExtraWarnings(true);
+        js_context->const_strings[i] = new JS::PersistentRootedId(cx,
+            gjs_intern_string_to_id(cx, const_strings[i]));
     }
 
-    if (!g_getenv("GJS_DISABLE_JIT")) {
-        gjs_debug(GJS_DEBUG_CONTEXT, "Enabling JIT");
-        JS::ContextOptionsRef(js_context->context)
-            .setIon(true)
-            .setBaseline(true)
-            .setAsmJS(true);
-    }
+    JS_BeginRequest(cx);
 
-    JS::RootedObject global(js_context->context,
-        gjs_create_global_object(js_context->context));
+    JS::RootedObject global(cx, gjs_create_global_object(cx));
     if (!global) {
         gjs_log_exception(js_context->context);
         g_error("Failed to initialize global object");
     }
 
-    JSAutoCompartment ac(js_context->context, global);
+    JSAutoCompartment ac(cx, global);
 
     new (&js_context->global) JS::Heap<JSObject *>(global);
-    JS_AddExtraGCRootsTracer(js_context->context, gjs_context_tracer,
-                             js_context);
+    JS_AddExtraGCRootsTracer(cx, gjs_context_tracer, js_context);
 
-    JS::RootedObject importer(js_context->context,
-        gjs_create_root_importer(js_context->context, js_context->search_path ?
-                                 js_context->search_path : nullptr));
+    JS::RootedObject importer(cx, gjs_create_root_importer(cx,
+        js_context->search_path ? js_context->search_path : nullptr));
     if (!importer)
         g_error("Failed to create root importer");
 
-    JS::Value v_importer = gjs_get_global_slot(js_context->context,
-                                               GJS_GLOBAL_SLOT_IMPORTS);
+    JS::Value v_importer = gjs_get_global_slot(cx, GJS_GLOBAL_SLOT_IMPORTS);
     g_assert(((void) "Someone else already created root importer",
               v_importer.isUndefined()));
 
-    gjs_set_global_slot(js_context->context, GJS_GLOBAL_SLOT_IMPORTS,
-                        JS::ObjectValue(*importer));
+    gjs_set_global_slot(cx, GJS_GLOBAL_SLOT_IMPORTS, JS::ObjectValue(*importer));
 
-    if (!gjs_define_global_properties(js_context->context, global)) {
-        gjs_log_exception(js_context->context);
+    if (!gjs_define_global_properties(cx, global)) {
+        gjs_log_exception(cx);
         g_error("Failed to define properties on global object");
     }
 
-    JS_EndRequest(js_context->context);
+    JS_EndRequest(cx);
 
     g_mutex_lock (&contexts_lock);
     all_contexts = g_list_prepend(all_contexts, object);
@@ -472,6 +432,20 @@ _gjs_context_get_is_owner_thread(GjsContext *js_context)
     return js_context->owner_thread == g_thread_self();
 }
 
+void
+_gjs_context_set_sweeping(GjsContext *js_context,
+                          bool        sweeping)
+{
+    js_context->in_gc_sweep = sweeping;
+}
+
+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/engine.cpp
similarity index 64%
rename from gjs/runtime.cpp
rename to gjs/engine.cpp
index 3f7aaff..9676166 100644
--- a/gjs/runtime.cpp
+++ b/gjs/engine.cpp
@@ -26,27 +26,17 @@
 #include "jsapi-wrapper.h"
 #include <js/Initialization.h>
 
+#include "context-private.h"
+#include "engine.h"
+#include "gi/object.h"
 #include "jsapi-util.h"
-#include "runtime.h"
+#include "util/log.h"
 
 #ifdef G_OS_WIN32
 #define WIN32_LEAN_AND_MEAN
 #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 +134,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,
@@ -168,9 +146,9 @@ static void
 gjs_finalize_callback(JSFreeOp         *fop,
                       JSFinalizeStatus  status,
                       bool              isCompartment,
-                      void             *user_data)
+                      void             *data)
 {
-  RuntimeData *data = static_cast<RuntimeData *>(user_data);
+    auto js_context = static_cast<GjsContext *>(data);
 
   /* Implementation note for mozjs 24:
      sweeping happens in two phases, in the first phase all
@@ -213,17 +191,22 @@ gjs_finalize_callback(JSFreeOp         *fop,
   */
 
   if (status == JSFINALIZE_GROUP_START)
-    data->in_gc_sweep = true;
+        _gjs_context_set_sweeping(js_context, true);
   else if (status == JSFINALIZE_GROUP_END)
-    data->in_gc_sweep = false;
+        _gjs_context_set_sweeping(js_context, 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)
+on_garbage_collect(JSContext *cx,
+                   JSGCStatus status,
+                   void      *data)
 {
-    g_private_replace(&thread_runtime, NULL);
+    /* We finalize any pending toggle refs before doing any garbage collection,
+     * so that we can collect the JS wrapper objects, and in order to minimize
+     * the chances of objects having a pending toggle up queued when they are
+     * garbage collected. */
+    if (status == JSGC_BEGIN)
+        gjs_object_clear_toggles();
 }
 
 #ifdef G_OS_WIN32
@@ -243,7 +226,6 @@ LPVOID    lpvReserved)
     break;
 
   case DLL_THREAD_DETACH:
-    gjs_destroy_runtime_for_current_thread();
     JS_ShutDown ();
     break;
 
@@ -264,8 +246,6 @@ public:
     }
 
     ~GjsInit() {
-        /* No-op if the runtime was already destroyed */
-        gjs_destroy_runtime_for_current_thread();
         JS_ShutDown();
     }
 
@@ -277,69 +257,52 @@ public:
 static GjsInit gjs_is_inited;
 #endif
 
-static JSRuntime *
-gjs_runtime_for_current_thread(void)
+JSContext *
+gjs_create_js_context(GjsContext *js_context)
 {
-    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::SetWarningReporter(runtime, gjs_warning_reporter);
-
-        g_private_set(&thread_runtime, runtime);
+    g_assert(gjs_is_inited);
+    JSContext *cx = JS_NewContext(32 * 1024 * 1024 /* max bytes */);
+    if (!cx)
+        return nullptr;
+
+    // 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);
+
+    /* set ourselves as the private data */
+    JS_SetContextPrivate(cx, js_context);
+
+    JS_AddFinalizeCallback(cx, gjs_finalize_callback, js_context);
+    JS_SetGCCallback(cx, on_garbage_collect, js_context);
+    JS_SetLocaleCallbacks(cx, &gjs_locale_callbacks);
+    JS::SetWarningReporter(cx, gjs_warning_reporter);
+
+    /* setExtraWarnings: Be extra strict about code that might hide a bug */
+    if (!g_getenv("GJS_DISABLE_EXTRA_WARNINGS")) {
+        gjs_debug(GJS_DEBUG_CONTEXT, "Enabling extra warnings");
+        JS::ContextOptionsRef(cx).setExtraWarnings(true);
     }
 
-    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;
-}
+    if (!g_getenv("GJS_DISABLE_JIT")) {
+        gjs_debug(GJS_DEBUG_CONTEXT, "Enabling JIT");
+        JS::ContextOptionsRef(cx)
+            .setIon(true)
+            .setBaseline(true)
+            .setAsmJS(true);
+    }
 
-/* No-op if there is no runtime */
-void
-gjs_runtime_unref(void)
-{
-    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();
+    return cx;
 }
diff --git a/gjs/runtime.h b/gjs/engine.h
similarity index 83%
rename from gjs/runtime.h
rename to gjs/engine.h
index 6f31fd2..46bce81 100644
--- a/gjs/runtime.h
+++ b/gjs/engine.h
@@ -21,14 +21,12 @@
  * IN THE SOFTWARE.
  */
 
-#ifndef __GJS_RUNTIME_H__
-#define __GJS_RUNTIME_H__
+#ifndef GJS_ENGINE_H
+#define GJS_ENGINE_H
 
-#include <stdbool.h>
+#include "context.h"
+#include "jsapi-wrapper.h"
 
-JSRuntime *gjs_runtime_ref(void);
-void gjs_runtime_unref(void);
+JSContext *gjs_create_js_context(GjsContext *js_context);
 
-bool        gjs_runtime_is_sweeping        (JSRuntime *runtime);
-
-#endif /* __GJS_RUNTIME_H__ */
+#endif  /* GJS_ENGINE_H */
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 32b300d..363dc95 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -30,7 +30,6 @@
 #include <glib-object.h>
 
 #include "jsapi-wrapper.h"
-#include "gjs/runtime.h"
 #include "gi/gtype.h"
 
 class GjsAutoChar : public std::unique_ptr<char, decltype(&g_free)> {


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