[gjs/wip/ptomato/mozjs38: 3/28] js: Implement barriers correctly in structs



commit f0b2c14d64b50ab953b9cec1361d3f09f4f740fa
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Jan 10 20:27:19 2017 -0800

    js: Implement barriers correctly in structs
    
    Fundamental was the only class that didn't have the IMPLEMENTS_BARRIERS
    flag set. In SpiderMonkey 38 it's required on all classes that have a
    trace hook.
    
    In addition, in order to implement barriers correctly we need to make sure
    that JS::Heap's constructor and destructor are called. In most cases we do
    this by making the containing struct a C++ struct, and calling its
    constructor and destructor. In the case of GjsContext (a GObject struct)
    and GjsCoveragePrivate (a GObject private struct) we can't do that, so
    instead we use placement new on the JS::Heap member.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=776966

 gi/boxed.cpp       |    9 +++++++--
 gi/function.cpp    |    2 ++
 gi/function.h      |    4 ++--
 gi/fundamental.cpp |   11 +++++++----
 gjs/context.cpp    |    3 ++-
 gjs/coverage.cpp   |    2 ++
 6 files changed, 22 insertions(+), 9 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 09e20e3..9a76d5e 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -39,7 +39,7 @@
 
 #include <girepository.h>
 
-typedef struct {
+struct Boxed {
     /* prototype info */
     GIBoxedInfo *info;
     GType gtype;
@@ -56,7 +56,7 @@ typedef struct {
     guint allocated_directly : 1;
     guint not_owning_gboxed : 1; /* if set, the JS wrapper does not own
                                     the reference to the C gboxed */
-} Boxed;
+};
 
 static bool struct_is_simple(GIStructInfo *info);
 
@@ -410,6 +410,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
     GJS_NATIVE_CONSTRUCTOR_PRELUDE(boxed);
 
     priv = g_slice_new0(Boxed);
+    new (priv) Boxed();
 
     GJS_INC_COUNTER(boxed);
 
@@ -506,6 +507,7 @@ boxed_finalize(JSFreeOp *fop,
     }
 
     GJS_DEC_COUNTER(boxed);
+    priv->~Boxed();
     g_slice_free(Boxed, priv);
 }
 
@@ -576,6 +578,7 @@ get_nested_interface_object (JSContext   *context,
 
     GJS_INC_COUNTER(boxed);
     priv = g_slice_new0(Boxed);
+    new (priv) Boxed();
     JS_SetPrivate(obj, priv);
     priv->info = (GIBoxedInfo*) interface_info;
     g_base_info_ref( (GIBaseInfo*) priv->info);
@@ -1139,6 +1142,7 @@ gjs_define_boxed_class(JSContext       *context,
 
     GJS_INC_COUNTER(boxed);
     priv = g_slice_new0(Boxed);
+    new (priv) Boxed();
     priv->info = info;
     boxed_fill_prototype_info(context, priv);
 
@@ -1186,6 +1190,7 @@ gjs_boxed_from_c_struct(JSContext             *context,
 
     GJS_INC_COUNTER(boxed);
     priv = g_slice_new0(Boxed);
+    new (priv) Boxed();
 
     *priv = *proto_priv;
     g_base_info_ref( (GIBaseInfo*) priv->info);
diff --git a/gi/function.cpp b/gi/function.cpp
index d061d74..dc14281 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -93,6 +93,7 @@ gjs_callback_trampoline_unref(GjsCallbackTrampoline *trampoline)
         g_callable_info_free_closure(trampoline->info, trampoline->closure);
         g_base_info_unref( (GIBaseInfo*) trampoline->info);
         g_free (trampoline->param_types);
+        trampoline->~GjsCallbackTrampoline();
         g_slice_free(GjsCallbackTrampoline, trampoline);
     }
 }
@@ -449,6 +450,7 @@ gjs_callback_trampoline_new(JSContext      *context,
     g_assert(JS_TypeOfValue(context, function) == JSTYPE_FUNCTION);
 
     trampoline = g_slice_new(GjsCallbackTrampoline);
+    new (trampoline) GjsCallbackTrampoline();
     trampoline->ref_count = 1;
     trampoline->context = context;
     trampoline->info = callable_info;
diff --git a/gi/function.h b/gi/function.h
index 234b551..8bc9cb1 100644
--- a/gi/function.h
+++ b/gi/function.h
@@ -41,7 +41,7 @@ typedef enum {
     PARAM_CALLBACK
 } GjsParamType;
 
-typedef struct {
+struct GjsCallbackTrampoline {
     gint ref_count;
     JSContext *context;
     GICallableInfo *info;
@@ -51,7 +51,7 @@ typedef struct {
     GIScopeType scope;
     bool is_vfunc;
     GjsParamType *param_types;
-} GjsCallbackTrampoline;
+};
 
 GjsCallbackTrampoline* gjs_callback_trampoline_new(JSContext      *context,
                                                    JS::HandleValue function,
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 3245a18..91d2efe 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -43,10 +43,10 @@
 /*
  * Structure allocated for prototypes.
  */
-typedef struct _Fundamental {
+struct Fundamental {
     /* instance info */
     void                         *gfundamental;
-    struct _Fundamental          *prototype;    /* NULL if prototype */
+    Fundamental                  *prototype;    /* NULL if prototype */
 
     /* prototype info */
     GIObjectInfo                 *info;
@@ -58,14 +58,14 @@ typedef struct _Fundamental {
 
     JS::Heap<jsid>                constructor_name;
     GICallableInfo               *constructor_info;
-} Fundamental;
+};
 
 /*
  * Structure allocated for instances.
  */
 typedef struct {
     void                         *gfundamental;
-    struct _Fundamental          *prototype;
+    Fundamental                  *prototype;
 } FundamentalInstance;
 
 extern struct JSClass gjs_fundamental_instance_class;
@@ -477,6 +477,7 @@ fundamental_finalize(JSFreeOp  *fop,
             g_base_info_unref((GIBaseInfo *) proto_priv->info);
         proto_priv->info = NULL;
 
+        proto_priv->~Fundamental();
         g_slice_free(Fundamental, proto_priv);
     }
 }
@@ -538,6 +539,7 @@ fundamental_trace(JSTracer *tracer,
 struct JSClass gjs_fundamental_instance_class = {
     "GFundamental_Object",
     JSCLASS_HAS_PRIVATE |
+    JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_NEW_RESOLVE,
     JS_PropertyStub,
     JS_DeletePropertyStub,
@@ -692,6 +694,7 @@ gjs_define_fundamental_class(JSContext              *context,
 
     /* Put the info in the prototype */
     priv = g_slice_new0(Fundamental);
+    new (priv) Fundamental();
     g_assert(priv != NULL);
     g_assert(priv->info == NULL);
     priv->info = g_base_info_ref((GIBaseInfo *) info);
diff --git a/gjs/context.cpp b/gjs/context.cpp
index e814841..35693d8 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -441,6 +441,7 @@ gjs_context_finalize(GObject *object)
     all_contexts = g_list_remove(all_contexts, object);
     g_mutex_unlock(&contexts_lock);
 
+    js_context->global.~Heap();
     G_OBJECT_CLASS(gjs_context_parent_class)->finalize(object);
 }
 
@@ -487,7 +488,7 @@ gjs_context_constructed(GObject *object)
     if (!JS_DefineFunctions(js_context->context, global, &global_funcs[0]))
         g_error("Failed to define properties on the global object");
 
-    js_context->global = global;
+    new (&js_context->global) JS::Heap<JSObject *>(global);
     JS_AddExtraGCRootsTracer(js_context->runtime, gjs_context_tracer, js_context);
 
     gjs_define_constructor_proxy_factory(js_context->context);
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index 3304141..5775c35 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -1706,6 +1706,7 @@ gjs_coverage_constructed(GObject *object)
 
     GjsCoverage *coverage = GJS_COVERAGE(object);
     GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
+    new (&priv->coverage_statistics) JS::Heap<JSObject *>();
 
     if (!priv->cache_specified) {
         g_message("Cache path was not given, picking default one");
@@ -1805,6 +1806,7 @@ gjs_coverage_finalize (GObject *object)
     g_strfreev(priv->prefixes);
     g_clear_object(&priv->output_dir);
     g_clear_object(&priv->cache);
+    priv->coverage_statistics.~Heap();
 
     G_OBJECT_CLASS(gjs_coverage_parent_class)->finalize(object);
 }


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