[gjs/ewlsh/allocate-nullptrs: 14/14] Proposal; squash if acceptable




commit eeb7b91911ad3b04638421793d414382a1b91992
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Sep 19 14:31:33 2021 -0700

    Proposal; squash if acceptable

 gi/boxed.cpp | 89 +++++++++++++++++++++++++++++++++++++++---------------------
 gi/boxed.h   | 15 ++++------
 2 files changed, 64 insertions(+), 40 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 6d1fb400..6c62630a 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -46,8 +46,7 @@ BoxedInstance::BoxedInstance(JSContext* cx, JS::HandleObject obj)
     GJS_INC_COUNTER(boxed_instance);
 }
 
-[[nodiscard]] static bool struct_is_simple(
-    GIStructInfo* info, Gjs::DirectAllocationPolicy allocation_policy);
+[[nodiscard]] static bool struct_is_simple(GIStructInfo* info);
 
 // See GIWrapperBase::resolve().
 bool BoxedPrototype::resolve_impl(JSContext* cx, JS::HandleObject obj,
@@ -368,8 +367,7 @@ bool BoxedInstance::constructor_impl(JSContext* context, JS::HandleObject obj,
 
         debug_lifecycle("Boxed pointer created from zero-args constructor");
 
-    } else if (proto->can_allocate_directly(
-                   Gjs::DirectAllocationPolicy::NO_POINTERS)) {
+    } else if (proto->can_allocate_directly_without_pointers()) {
         allocate_directly();
     } else if (proto->has_default_constructor()) {
         /* for simplicity, we simply delegate all the work to the actual JS
@@ -481,8 +479,7 @@ bool BoxedInstance::get_nested_interface_object(
     GIBaseInfo* interface_info, JS::MutableHandleValue value) const {
     int offset;
 
-    if (!struct_is_simple(reinterpret_cast<GIStructInfo*>(interface_info),
-                          Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
+    if (!struct_is_simple ((GIStructInfo *)interface_info)) {
         gjs_throw(context, "Reading field %s.%s is not supported", name(),
                   g_base_info_get_name(field_info));
 
@@ -604,8 +601,7 @@ bool BoxedInstance::set_nested_interface_object(JSContext* context,
                                                 JS::HandleValue value) {
     int offset;
 
-    if (!struct_is_simple(reinterpret_cast<GIStructInfo*>(interface_info),
-                          Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
+    if (!struct_is_simple ((GIStructInfo *)interface_info)) {
         gjs_throw(context, "Writing field %s.%s is not supported", name(),
                   g_base_info_get_name(field_info));
 
@@ -781,7 +777,7 @@ const struct JSClass BoxedBase::klass = {
 // clang-format on
 
 [[nodiscard]] static bool type_can_be_allocated_directly(
-    GITypeInfo* type_info, Gjs::DirectAllocationPolicy allocation_policy) {
+    GITypeInfo* type_info) {
     bool is_simple = true;
 
     if (g_type_info_is_pointer(type_info)) {
@@ -789,16 +785,9 @@ const struct JSClass BoxedBase::klass = {
             g_type_info_get_array_type(type_info) == GI_ARRAY_TYPE_C) {
             GjsAutoBaseInfo param_info =
                 g_type_info_get_param_type(type_info, 0);
-            is_simple =
-                type_can_be_allocated_directly(param_info, allocation_policy);
-        } else if (g_type_info_get_tag(type_info) == GI_TYPE_TAG_VOID) {
-            return true;
-        } else if (allocation_policy ==
-                   Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS) {
-            return true;
-        } else {
-            is_simple = false;
+            return type_can_be_allocated_directly(param_info);
         }
+        return true;
     } else {
         switch (g_type_info_get_tag(type_info)) {
         case GI_TYPE_TAG_INTERFACE:
@@ -807,11 +796,7 @@ const struct JSClass BoxedBase::klass = {
             switch (g_base_info_get_type(interface)) {
                 case GI_INFO_TYPE_BOXED:
                 case GI_INFO_TYPE_STRUCT:
-                    if (!struct_is_simple(
-                            interface.as<GIStructInfo>(),
-                            Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS))
-                        is_simple = false;
-                    break;
+                    return struct_is_simple(interface.as<GIStructInfo>());
                 case GI_INFO_TYPE_UNION:
                     /* FIXME: Need to implement */
                     is_simple = false;
@@ -870,12 +855,37 @@ const struct JSClass BoxedBase::klass = {
     return is_simple;
 }
 
+[[nodiscard]] static bool simple_struct_has_pointers(GIStructInfo*);
+
+[[nodiscard]] static bool direct_allocation_has_pointers(
+    GITypeInfo* type_info) {
+    if (g_type_info_is_pointer(type_info)) {
+        if (g_type_info_get_tag(type_info) == GI_TYPE_TAG_ARRAY &&
+            g_type_info_get_array_type(type_info) == GI_ARRAY_TYPE_C) {
+            GjsAutoBaseInfo param_info =
+                g_type_info_get_param_type(type_info, 0);
+            return direct_allocation_has_pointers(param_info);
+        }
+
+        return g_type_info_get_tag(type_info) != GI_TYPE_TAG_VOID;
+    }
+
+    if (g_type_info_get_tag(type_info) != GI_TYPE_TAG_INTERFACE)
+        return false;
+
+    GjsAutoBaseInfo interface = g_type_info_get_interface(type_info);
+    if (interface.type() == GI_INFO_TYPE_BOXED ||
+        interface.type() == GI_INFO_TYPE_STRUCT)
+        return simple_struct_has_pointers(interface.as<GIStructInfo>());
+
+    return false;
+}
+
 /* Check if the type of the boxed is "simple" - every field is a non-pointer
  * type that we know how to assign to. If so, then we can allocate and free
  * instances without needing a constructor.
  */
-[[nodiscard]] static bool struct_is_simple(
-    GIStructInfo* info, Gjs::DirectAllocationPolicy allocation_policy) {
+[[nodiscard]] static bool struct_is_simple(GIStructInfo* info) {
     int n_fields = g_struct_info_get_n_fields(info);
     bool is_simple = true;
     int i;
@@ -888,22 +898,39 @@ const struct JSClass BoxedBase::klass = {
         GjsAutoBaseInfo field_info = g_struct_info_get_field(info, i);
         GjsAutoBaseInfo type_info = g_field_info_get_type(field_info);
 
-        is_simple =
-            type_can_be_allocated_directly(type_info, allocation_policy);
+        is_simple = type_can_be_allocated_directly(type_info);
     }
 
     return is_simple;
 }
 
+[[nodiscard]] static bool simple_struct_has_pointers(GIStructInfo* info) {
+    g_assert(struct_is_simple(info) &&
+             "Don't call simple_struct_has_pointers() on a non-simple struct");
+
+    int n_fields = g_struct_info_get_n_fields(info);
+    g_assert(n_fields > 0);
+
+    for (int i = 0; i < n_fields; i++) {
+        GjsAutoBaseInfo field_info = g_struct_info_get_field(info, i);
+        GjsAutoBaseInfo type_info = g_field_info_get_type(field_info);
+        if (direct_allocation_has_pointers(type_info))
+            return true;
+    }
+    return false;
+}
+
 BoxedPrototype::BoxedPrototype(GIStructInfo* info, GType gtype)
     : GIWrapperPrototype(info, gtype),
       m_zero_args_constructor(-1),
       m_default_constructor(-1),
       m_default_constructor_name(JSID_VOID),
-      m_can_allocate_directly(
-          struct_is_simple(info, Gjs::DirectAllocationPolicy::NO_POINTERS)),
-      m_can_allocate_directly_with_pointers(struct_is_simple(
-          info, Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
+      m_can_allocate_directly(struct_is_simple(info)) {
+    if (!m_can_allocate_directly)
+        m_can_allocate_directly_without_pointers = false;
+    else
+        m_can_allocate_directly_without_pointers =
+            !simple_struct_has_pointers(info);
     GJS_INC_COUNTER(boxed_prototype);
 }
 
diff --git a/gi/boxed.h b/gi/boxed.h
index 6287aea9..faaec5e9 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -96,8 +96,8 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
     int m_default_constructor;  // -1 if none
     JS::Heap<jsid> m_default_constructor_name;
     std::unique_ptr<FieldMap> m_field_map;
+    bool m_can_allocate_directly_without_pointers : 1;
     bool m_can_allocate_directly : 1;
-    bool m_can_allocate_directly_with_pointers : 1;
 
     explicit BoxedPrototype(GIStructInfo* info, GType gtype);
     ~BoxedPrototype(void);
@@ -109,14 +109,11 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
     // Accessors
 
  public:
-    [[nodiscard]] bool can_allocate_directly(
-        Gjs::DirectAllocationPolicy allocation_policy =
-            Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS) const {
-        if (allocation_policy == Gjs::DirectAllocationPolicy::NO_POINTERS) {
-            return m_can_allocate_directly;
-        }
-
-        return m_can_allocate_directly_with_pointers;
+    [[nodiscard]] bool can_allocate_directly_without_pointers() const {
+        return m_can_allocate_directly_without_pointers;
+    }
+    [[nodiscard]] bool can_allocate_directly() const {
+        return m_can_allocate_directly;
     }
     [[nodiscard]] bool has_zero_args_constructor() const {
         return m_zero_args_constructor >= 0;


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