[gjs/wip/ptomato/mozjs31prep: 2/2] context: Store global object as JS::Heap



commit 5d5acbb88e41fbc3d079759b0ad59476fa9538f8
Author: Philip Chimento <philip endlessm com>
Date:   Tue Oct 18 18:42:51 2016 -0700

    context: Store global object as JS::Heap
    
    "GC things" that are part of structures stored on the heap can't be
    rooted with JS::Rooted, as those objects must be rooted and unrooted in
    LIFO order for performance reasons.
    
    In this case, we need to root the global object with JS_AddRoot and
    JS_RemoveRoot. It also must be stored inside a JS::Heap because it is a
    member of a struct that is allocated on the heap. The JS::Heap keeps
    track of when the garbage collector moves the object, but it does not
    actually root the object.
    
    See this page for more information:
    http://trac.wildfiregames.com/wiki/JSRootingGuide

 gjs/context.cpp    |   22 ++++++++++++++++------
 gjs/jsapi-util.cpp |    9 +++------
 gjs/jsapi-util.h   |    4 ++--
 3 files changed, 21 insertions(+), 14 deletions(-)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 7596345..8c099c5 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -61,7 +61,7 @@ struct _GjsContext {
 
     JSRuntime *runtime;
     JSContext *context;
-    JSObject *global;
+    JS::Heap<JSObject*> global;
 
     char *program_name;
 
@@ -341,6 +341,10 @@ gjs_context_dispose(GObject *object)
                   "Destroying JS context");
 
         JS_BeginRequest(js_context->context);
+
+        JS_RemoveObjectRoot(js_context->context, js_context->global.unsafeGet());
+        js_context->global.set(NULL);
+
         /* Do a full GC here before tearing down, since once we do
          * that we may not have the JS_GetPrivate() to access the
          * context
@@ -426,21 +430,27 @@ gjs_context_constructed(GObject *object)
 
     /* set ourselves as the private data */
     JS_SetContextPrivate(js_context->context, js_context);
+    JS::RootedObject global(js_context->context);
 
-    if (!gjs_init_context_standard(js_context->context, &js_context->global))
+    if (!gjs_init_context_standard(js_context->context, &global))
         g_error("Failed to initialize context");
 
-    JSAutoCompartment ac(js_context->context, js_context->global);
+    JSAutoCompartment ac(js_context->context, global);
 
-    if (!JS_DefineProperty(js_context->context, js_context->global,
-                           "window", JS::ObjectValue(*js_context->global),
+    JS::RootedValue v_global(js_context->context, JS::ObjectValue(*global));
+    if (!JS_DefineProperty(js_context->context, global,
+                           "window", v_global,
                            NULL, NULL,
                            JSPROP_READONLY | JSPROP_PERMANENT))
         g_error("No memory to export global object as 'window'");
 
-    if (!JS_DefineFunctions(js_context->context, js_context->global, &global_funcs[0]))
+    if (!JS_DefineFunctions(js_context->context, global, &global_funcs[0]))
         g_error("Failed to define properties on the global object");
 
+    js_context->global.set(global);
+    JS_AddNamedObjectRoot(js_context->context, js_context->global.unsafeGet(),
+                          "global object");
+
     /* We create the global-to-runtime root importer with the
      * passed-in search path. If someone else already created
      * the root importer, this is a no-op.
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index cd65759..81f468c 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -62,10 +62,9 @@ static JSClass global_class = {
  * Returns: true on success, false otherwise
  */
 bool
-gjs_init_context_standard (JSContext  *context,
-                           JSObject  **global_out)
+gjs_init_context_standard (JSContext              *context,
+                           JS::MutableHandleObject global)
 {
-    JSObject *global;
     JS::CompartmentOptions options;
     guint32 options_flags;
 
@@ -91,7 +90,7 @@ gjs_init_context_standard (JSContext  *context,
     JS_SetErrorReporter(context, gjs_error_reporter);
 
     options.setVersion(JSVERSION_LATEST);
-    global = JS_NewGlobalObject(context, &global_class, NULL, options);
+    global.set(JS_NewGlobalObject(context, &global_class, NULL, options));
     if (global == NULL)
         return false;
 
@@ -107,8 +106,6 @@ gjs_init_context_standard (JSContext  *context,
     if (!JS_DefineDebuggerObject(context, global))
         return false;
 
-    *global_out = global;
-
     return true;
 }
 
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index a757965..258c139 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -290,8 +290,8 @@ gjs_##name##_constructor(JSContext  *context,           \
         return false;                                           \
     }
 
-bool        gjs_init_context_standard        (JSContext       *context,
-                                              JSObject       **global_out);
+bool gjs_init_context_standard(JSContext              *context,
+                               JS::MutableHandleObject global);
 
 JSObject*   gjs_get_import_global            (JSContext       *context);
 


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