[gjs/wip/require: 23/29] runtime: Have a thread-specific JSRuntime



commit e47266c022191c9577daa9e915bbc77b27a5a9ee
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Wed Jan 15 10:57:18 2014 -0500

    runtime: Have a thread-specific JSRuntime
    
    JSRuntime needs to match 1:1 to a thread, so if we have more than
    one runtime in a thread, like we did in the test suite before, we
    would blow up.

 gjs/context.cpp |  133 +----------------------------------------------
 gjs/runtime.cpp |  158 ++++++++++++++++++++++++++++++++++++++++++++++---------
 gjs/runtime.h   |    4 +-
 3 files changed, 135 insertions(+), 160 deletions(-)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 591a25d..afa8a38 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -346,13 +346,6 @@ gjs_context_dispose(GObject *object)
 
         JS_DestroyContext(js_context->context);
         js_context->context = NULL;
-    }
-
-    if (js_context->runtime != NULL) {
-        gjs_runtime_deinit(js_context->runtime);
-
-        /* Cleans up data as well as destroying the runtime. */
-        JS_DestroyRuntime(js_context->runtime);
         js_context->runtime = NULL;
     }
 
@@ -386,122 +379,6 @@ gjs_context_finalize(GObject *object)
     G_OBJECT_CLASS(gjs_context_parent_class)->finalize(object);
 }
 
-/* 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
- * to UTF-8, using the appropriate GLib functions, and converting
- * back if necessary.
- */
-static JSBool
-gjs_locale_to_upper_case (JSContext *context,
-                          JS::HandleString src,
-                          JS::MutableHandleValue retval)
-{
-    JSBool success = JS_FALSE;
-    char *utf8 = NULL;
-    char *upper_case_utf8 = NULL;
-
-    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src), &utf8))
-        goto out;
-
-    upper_case_utf8 = g_utf8_strup (utf8, -1);
-
-    if (!gjs_string_from_utf8(context, upper_case_utf8, -1, retval.address()))
-        goto out;
-
-    success = JS_TRUE;
-
-out:
-    g_free(utf8);
-    g_free(upper_case_utf8);
-
-    return success;
-}
-
-static JSBool
-gjs_locale_to_lower_case (JSContext *context,
-                          JS::HandleString src,
-                          JS::MutableHandleValue retval)
-{
-    JSBool success = JS_FALSE;
-    char *utf8 = NULL;
-    char *lower_case_utf8 = NULL;
-
-    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src), &utf8))
-        goto out;
-
-    lower_case_utf8 = g_utf8_strdown (utf8, -1);
-
-    if (!gjs_string_from_utf8(context, lower_case_utf8, -1, retval.address()))
-        goto out;
-
-    success = JS_TRUE;
-
-out:
-    g_free(utf8);
-    g_free(lower_case_utf8);
-
-    return success;
-}
-
-static JSBool
-gjs_locale_compare (JSContext *context,
-                    JS::HandleString src_1,
-                    JS::HandleString src_2,
-                    JS::MutableHandleValue retval)
-{
-    JSBool success = JS_FALSE;
-    char *utf8_1 = NULL, *utf8_2 = NULL;
-    int result;
-
-    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src_1), &utf8_1) ||
-        !gjs_string_to_utf8(context, STRING_TO_JSVAL(src_2), &utf8_2))
-        goto out;
-
-    result = g_utf8_collate (utf8_1, utf8_2);
-    retval.set(INT_TO_JSVAL(result));
-
-    success = JS_TRUE;
-
-out:
-    g_free(utf8_1);
-    g_free(utf8_2);
-
-    return success;
-}
-
-static JSBool
-gjs_locale_to_unicode (JSContext  *context,
-                       const char *src,
-                       JS::MutableHandleValue retval)
-{
-    JSBool success;
-    char *utf8;
-    GError *error = NULL;
-
-    utf8 = g_locale_to_utf8(src, -1, NULL, NULL, &error);
-    if (!utf8) {
-        gjs_throw(context,
-                  "Failed to convert locale string to UTF8: %s",
-                  error->message);
-        g_error_free(error);
-        return JS_FALSE;
-    }
-
-    success = gjs_string_from_utf8(context, utf8, -1, retval.address());
-    g_free (utf8);
-
-    return success;
-}
-
-static JSLocaleCallbacks gjs_locale_callbacks =
-{
-    gjs_locale_to_upper_case,
-    gjs_locale_to_lower_case,
-    gjs_locale_compare,
-    gjs_locale_to_unicode
-};
-
 static void
 gjs_context_constructed(GObject *object)
 {
@@ -511,18 +388,12 @@ gjs_context_constructed(GObject *object)
 
     G_OBJECT_CLASS(gjs_context_parent_class)->constructed(object);
 
-    js_context->runtime = JS_NewRuntime(32*1024*1024 /* max bytes */, JS_USE_HELPER_THREADS);
-    JS_SetNativeStackQuota(js_context->runtime, 1024*1024);
-    if (js_context->runtime == NULL)
-        g_error("Failed to create javascript runtime");
-    JS_SetGCParameter(js_context->runtime, JSGC_MAX_BYTES, 0xffffffff);
+    js_context->runtime = gjs_runtime_for_current_thread();
 
     js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */);
     if (js_context->context == NULL)
         g_error("Failed to create javascript context");
 
-    gjs_runtime_init_for_context(js_context->runtime, js_context->context);
-
     for (i = 0; i < GJS_STRING_LAST; i++)
         js_context->const_strings[i] = gjs_intern_string_to_id(js_context->context, const_strings[i]);
 
@@ -544,8 +415,6 @@ gjs_context_constructed(GObject *object)
     JS_SetOptions(js_context->context,
                   JS_GetOptions(js_context->context) | options_flags);
 
-    JS_SetLocaleCallbacks(js_context->runtime, &gjs_locale_callbacks);
-
     JS_SetErrorReporter(js_context->context, gjs_error_reporter);
 
     /* set ourselves as the private data */
diff --git a/gjs/runtime.cpp b/gjs/runtime.cpp
index c9acebd..68a2cc8 100644
--- a/gjs/runtime.cpp
+++ b/gjs/runtime.cpp
@@ -23,41 +23,149 @@
 
 #include <config.h>
 
-#include <util/log.h>
-#include <util/glib.h>
-#include <util/misc.h>
-
-#include "jsapi-util.h"
 #include "compat.h"
-#include "jsapi-private.h"
-#include "runtime.h"
 
-#include <string.h>
-#include <math.h>
+/* 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
+ * to UTF-8, using the appropriate GLib functions, and converting
+ * back if necessary.
+ */
+static JSBool
+gjs_locale_to_upper_case (JSContext *context,
+                          JS::HandleString src,
+                          JS::MutableHandleValue retval)
+{
+    JSBool success = JS_FALSE;
+    char *utf8 = NULL;
+    char *upper_case_utf8 = NULL;
+
+    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src), &utf8))
+        goto out;
+
+    upper_case_utf8 = g_utf8_strup (utf8, -1);
 
-typedef struct {
-    JSContext *context;
-} GjsRuntimeData;
+    if (!gjs_string_from_utf8(context, upper_case_utf8, -1, retval.address()))
+        goto out;
+
+    success = JS_TRUE;
+
+out:
+    g_free(utf8);
+    g_free(upper_case_utf8);
+
+    return success;
+}
 
-static inline GjsRuntimeData *
-get_data(JSRuntime *runtime)
+static JSBool
+gjs_locale_to_lower_case (JSContext *context,
+                          JS::HandleString src,
+                          JS::MutableHandleValue retval)
 {
-    return (GjsRuntimeData*) JS_GetRuntimePrivate(runtime);
+    JSBool success = JS_FALSE;
+    char *utf8 = NULL;
+    char *lower_case_utf8 = NULL;
+
+    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src), &utf8))
+        goto out;
+
+    lower_case_utf8 = g_utf8_strdown (utf8, -1);
+
+    if (!gjs_string_from_utf8(context, lower_case_utf8, -1, retval.address()))
+        goto out;
+
+    success = JS_TRUE;
+
+out:
+    g_free(utf8);
+    g_free(lower_case_utf8);
+
+    return success;
 }
 
-void
-gjs_runtime_init_for_context(JSRuntime *runtime,
-                             JSContext *context)
+static JSBool
+gjs_locale_compare (JSContext *context,
+                    JS::HandleString src_1,
+                    JS::HandleString src_2,
+                    JS::MutableHandleValue retval)
 {
-    GjsRuntimeData *data;
+    JSBool success = JS_FALSE;
+    char *utf8_1 = NULL, *utf8_2 = NULL;
+    int result;
+
+    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src_1), &utf8_1) ||
+        !gjs_string_to_utf8(context, STRING_TO_JSVAL(src_2), &utf8_2))
+        goto out;
+
+    result = g_utf8_collate (utf8_1, utf8_2);
+    retval.set(INT_TO_JSVAL(result));
+
+    success = JS_TRUE;
 
-    data = g_new(GjsRuntimeData, 1);
-    data->context = context;
-    JS_SetRuntimePrivate(runtime, data);
+out:
+    g_free(utf8_1);
+    g_free(utf8_2);
+
+    return success;
 }
 
-void
-gjs_runtime_deinit(JSRuntime *runtime)
+static JSBool
+gjs_locale_to_unicode (JSContext  *context,
+                       const char *src,
+                       JS::MutableHandleValue retval)
 {
-    g_free(get_data(runtime));
+    JSBool success;
+    char *utf8;
+    GError *error = NULL;
+
+    utf8 = g_locale_to_utf8(src, -1, NULL, NULL, &error);
+    if (!utf8) {
+        gjs_throw(context,
+                  "Failed to convert locale string to UTF8: %s",
+                  error->message);
+        g_error_free(error);
+        return JS_FALSE;
+    }
+
+    success = gjs_string_from_utf8(context, utf8, -1, retval.address());
+    g_free (utf8);
+
+    return success;
+}
+
+static void
+destroy_runtime(gpointer data)
+{
+    JSRuntime *runtime = (JSRuntime *) data;
+    JS_DestroyRuntime(runtime);
+}
+
+static GPrivate thread_runtime = G_PRIVATE_INIT(destroy_runtime);
+
+static JSLocaleCallbacks gjs_locale_callbacks =
+{
+    gjs_locale_to_upper_case,
+    gjs_locale_to_lower_case,
+    gjs_locale_compare,
+    gjs_locale_to_unicode
+};
+
+JSRuntime *
+gjs_runtime_for_current_thread(void)
+{
+    JSRuntime *runtime = (JSRuntime *) g_private_get(&thread_runtime);
+
+    if (!runtime) {
+        runtime = JS_NewRuntime(32*1024*1024 /* max bytes */, JS_USE_HELPER_THREADS);
+        if (runtime == NULL)
+            g_error("Failed to create javascript runtime");
+
+        JS_SetNativeStackQuota(runtime, 1024*1024);
+        JS_SetGCParameter(runtime, JSGC_MAX_BYTES, 0xffffffff);
+        JS_SetLocaleCallbacks(runtime, &gjs_locale_callbacks);
+
+        g_private_set(&thread_runtime, runtime);
+    }
+
+    return runtime;
 }
diff --git a/gjs/runtime.h b/gjs/runtime.h
index 17e4364..90233b0 100644
--- a/gjs/runtime.h
+++ b/gjs/runtime.h
@@ -24,8 +24,6 @@
 #ifndef __GJS_RUNTIME_H__
 #define __GJS_RUNTIME_H__
 
-void        gjs_runtime_init_for_context     (JSRuntime       *runtime,
-                                              JSContext       *context);
-void        gjs_runtime_deinit               (JSRuntime       *runtime);
+JSRuntime * gjs_runtime_for_current_thread (void);
 
 #endif /* __GJS_RUNTIME_H__ */


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